繼承與多型中常見的問題分析
1、畫出派生類derive的記憶體布局
(1)如果base中的show函式是虛函式,那麼p->show();則動態繫結,列印出derive::show();
(2)如果base中的show函式不是虛函式,derive中的show函式不是虛函式,那麼p->show(),則靜態繫結,列印出base::show();
(3)如果base中的show函式不是虛函式,derive中的show函式是虛函式,那麼p->show(),則在編譯器發現base::show()不是虛函式,則不會發生動態繫結,故列印base::show();此時的記憶體布局是:
但是在執行上述main()**中,執行到delete p時會崩潰。原因是:基類指標指向派生類物件,指標永遠指向基類部分的起始位址,但是此時派生類的起始位址和基類的起始位址不在一起,故從基類起始位址處釋放則會崩潰。(開闢和釋放的記憶體不在一起)
注:delete呼叫的析構函式是指標型別 。new和delete兩者配對使用,兩者不配對使用的情況有:(1)自定義型別 (2)提供了自定義型別的析構函式
2、為什麼要將基類的析構函式寫為虛函式?
由以上可知:當基類物件指標指向堆上的派生類物件時,需要將基類 的析構函式寫為虛析構函式。
3、
#includeusing namespace std;
class base
; base( int data ) ;//執行clear()前的彙編指令為:
/*
push ebp
mov ebp,esp
sub esp,4ch
rep ……
vftable->vfptr
*/
void clear()
virtual void show()
此時程式崩潰的原因是:在呼叫建構函式base時,呼叫了clear()將記憶體中的元素清空為0,(也將前4個位元組(存放vfptr)置為0)
(2)
int main()
(3)去掉base建構函式中的clear(),給base和derive建構函式中加上show(),並不會發生動態繫結,因為在建構函式中物件還沒有生成,不會發生多型。
(4)在base的析構函式中呼叫show();,此時不會發生動態繫結,因為析構完後物件已經不存在了,所以不會發生。
(5)將派生類中的成員函式設為私有的,在編譯時期,是否會發生編譯錯誤?(訪問限定符只可以在編譯階段起作用)
由此可見:將派生類的虛函式設為私有的,編譯不會出錯,此時這個函式能否被呼叫主要取決於基類中該虛函式的訪問限定符。 4、
注:成員能不能被訪問,訪問許可權是否正確?函式的預設值用哪個?這些均是在編譯時期都已經確定好了,最終呼叫哪個派生類物件的方法在執行時確定。(在虛表中取誰的位址,執行時就呼叫誰)。
繼承和多型中常見的問題(一)
繼承和多型中常見的問題 一 一 繼承 的復用。繼承允許我們依據另乙個類來定義乙個類,這使得建立和維護乙個應用程式變得更容易。這樣做,也達到了重用 功能和提高執行時間的效果。1 繼承的方式 由於c 中有三種訪問限定符,public,private,protected.因此在類與類的繼承中也將有這三種方...
C 繼承與多型(二)
多型 虛函式 類成員函式前面加virtual關鍵字 虛函式重寫 當在子類的定義了乙個與父類完全相同的虛函式時,則稱子類的這個函式重寫了這個父類的這個虛函式 滿足條件 1.虛函式的重寫 2.父類的指標 引用呼叫虛函式 多型跟型別無關,與物件有關 多型 當使用基類的指標或引用調重寫的虛函式時,當指向父類...
c (八) 繼承與多型(二)
一 抽象類與動態型別轉換 1 訪問控制屬性 類的定義中有public private和protected三個關鍵字,其中private關鍵字說明類中成員為私有成員,只能在類內的函式訪問 public成員為公有成員,可被任何其他類訪問,protected關鍵字是保護屬性,保護屬性的資料或函式可被派生類...