為什麼父類指標可以指向子類,反之則不行?

2021-08-09 13:54:18 字數 3044 閱讀 6116

為什麼父類指標可以指向子類反之則不行?

例如:[cpp]

view plain

copy

class

a  ;  

class

b : 

public

a  ;

從記憶體的來看

如a[plain]

view plain

copy

先看a|---------|  

|佔乙個int資料大小|

|----(aa資料)---|  

而b則是  

|-----------|----------|  

|佔乙個int資料大小--|佔乙個int資料大小--|  

|從a中繼承而來------|----(bb資料)------|  

當定義乙個基類型別的指標時 

a *p; 這個指標指向的是a型別的資料,

當p指標指向派生類的時候,因為p是a型別的指標,所以*p只解釋為a型別資料的長度,即

[plain]

view plain

copy

|------------------|-----------------|

|佔乙個int資料大小--|佔乙個int資料大小--|  

|從a中繼承而來------|-----(bb資料)----|  

|--p只指向這個區域--|  

因此,當基類的指標(p)指向派生類的時候,只能操作派生類中從基類中繼承過來的資料。

反之,指向派生類的指標,因為記憶體空間比基類長,會導致嚴重後果,所以不允許派生類的指標指向基類。

通常來說,子類總是含有一些父類沒有的成員變數,或者方法函式。

而子類肯定含有父類所有的成員變數和方法函式。所以用父類指標指向子類時,沒有問題,因為父類有的,子類都有,不會出現非法訪問問題。

但是如果用子類指標指向父類的話,一旦訪問子類特有的方法函式或者成員變數,就會出現非法,因為被子類指標指向的父類物件,根本沒有子類要訪問的那些成員,那些是子類特有的,只有用子類初始化物件時才會有。

父類指標指向子類的例項:

1. 無論父類裡面有沒有虛函式

,都可以定義指向子類例項的父類指標. 

2.  如果父類裡沒有虛函式

,則使用父類指標

,只能訪問父類的成員

,而不能訪問子類裡的成員.

3.  如果父類裡的虛函式不是純虛函式

,且子類裡沒有重寫該虛函式

,則用父類指標訪問該虛函式的時候

,跟訪問父類裡的普通函式一樣.

4. 如果父類裡的虛函式不是純虛函式

,且子類裡重寫了該虛函式

,則用父類指標訪問該虛函式的時候訪問的是子類裡重寫後的函式

.        5. 

如果父類裡的虛函式是純虛函式

,則父類是個抽象類

,子類要想能夠被例項化

,則必須重寫該純虛函式

.用父類指標訪問該純虛函式的時候

,訪問到的是子類裡重寫了的函式.

6.再有乙個要注意的是析構函式要宣告為虛函式

,這樣在

delete

父類指標的時候

,才會呼叫例項化的子類的虛函式

,否則只會呼叫父類的析構函式

,造成子類的剩餘部分沒被釋放

,從而造成記憶體的洩漏.

總結:當定義乙個指向子類例項的父類指標的時候

,記憶體中例項化了子類

,由於子類繼承了父類

,因此記憶體中的子類裡包含父類的所有成員

.但由於宣告的是父類指標

,因此該指標不能夠訪問子類的成員

.而只能訪問父類的成員

.然而在父類裡可以宣告純虛函式和定義虛函式

.使用父類指標訪問虛函式或純虛函式的時候

,訪問到的是子類裡重寫的函式

. 當然

,對於虛函式

,如果子類裡沒有對其重寫的話

,仍然訪問到父類裡定義的虛函式

.可見虛函式和純虛函式的卻別僅僅在於

:純虛函式沒有定義

,只有宣告

,而且它使擁

這個問題牽扯到c++的物件模型。一般認為子類物件大小》=父類物件大小。為什麼?因為子類可以擴充套件父類,可以增加成員變數。如果乙個子類增加了成員變數,那麼它的物件的記憶體空間會大於父類物件。這時乙個實際指向父類的指標,如果被強制轉化為子類物件指標,當使用這個指標時可能會導致越界訪問非法記憶體。相反,為何子類指標可以轉換為父類指標?因為父類指標需要的,子類物件都有,不會出現非法記憶體訪問。

這就是dynamic_cast不一定成功的原因。

如果乙個實際指向子類物件的指標被轉換成了父類指標,然後再用dynamic_cast轉換回來,一定能成功,而乙個實際指向父類物件的指標,被dynamic_cast轉換為子類指標,一定會失敗。

今天看c++的書,測試了一下父類和子類指標互相指向父類和子類的情況會發生的情況.(未使用虛函式)

父類指標指向父類本身,只能訪問父類有的成員變數和成員函式.

子類指標指向子類本身,如果子類覆蓋了父類有的成員變數和成員函式訪問子類的成員變數和成員函式.如果子類沒有覆蓋父類的,則訪問父類的成員變數和函式

若父類指標指向子類,編譯器是可以通過的,該指標只能訪問父類的成員變數和函式

若子類指標指向父類,編譯器會報錯,我們使用型別強轉,將父類指標變為子類指標.此時我們再用子類指標時,我們可以發現,我們可以用子類指標訪問任意子類的成員變數和成員函式.哪怕該指標實際指向的時乙個父類的物件.

這一度使自己比較迷惑,後來經過研究,得出結論.因為該指標的型別已經轉化為子類指標,所以所有操作都會被看為子類,包括成員函式和成員變數.對於成員函式,函式的儲存位址使在**段,所以直接可以訪問.至於成員變數,編譯器會將子類指標指向的位址當成乙個子類的記憶體分布來對待,哪怕該段位址上只是乙個父類的物件,也就是說,如果訪問了子類中有而父類沒有的物件,那麼其實指標的訪問已經越界了,可能已經修改了其他變數的值了,這樣是很危險的.

綜上所述,其實不管父類和子類的指標如何指向互相的物件,編譯器的操作只會按照指標的型別來做出相應的動作.如果是乙個子類指標,無論指向的位址是不是父類,哪怕是乙個int型變數的位址,也會按照乙個子類的記憶體分布去操作.父類指標同理.因此在操作c指標時要特別注意.

為什麼父類指標可以指向子類反之則不行

分類 c c c c 2010 11 14 00 28 193人閱讀收藏 舉報例如 class a class b public a 從記憶體的來看 如a 佔乙個int資料大小 aa資料 而b則是 佔乙個int資料大小 佔乙個int資料大小 從a中繼承而來 bb資料 當定義乙個基類型別的指標時 a ...

父類指標可以指向子類物件,反之則不能。

最近準備考研複試內容,都是c c 選擇題,做點筆記。簡單來說,c 的多型就是靠父類指標指向子類物件 虛函式來實現的。父類指標指向子類物件,可以呼叫子類從父類繼承來的那一部分,但如果父類中宣告了virtual,則可以呼叫子類中的方法,這樣就實現了多型。而子類指標指向父類物件,可能會呼叫到父類中沒用的方...

c 父類指標指向子類物件

父類子類指標函式呼叫注意事項 1,如果以乙個基礎類指標指向乙個衍生類物件 派生類物件 那麼經由該指標只能訪問基礎類定義的函式 靜態聯翩 2,如果以乙個衍生類指標指向乙個基礎類物件,必須先做強制轉型動作 explicit cast 這種做法很危險,也不符合生活習慣,在程式設計上也會給程式設計師帶來困擾...