多型的實現條件
多型(與物件有關 到物件的虛表中找到)=動態聯編+虛函式重寫
動態聯編(執行時決議):指標/引用+虛函式
靜態聯編(編譯時決議)與型別有關,像函式過載和通過物件名呼叫虛函式
1.定義乙個父類的指標,如果這個指標指向父類,呼叫父類的虛函式,指標指向子類,呼叫子類的虛函式,這樣可以使乙個函式有不同的實現,即多型的體現。
2.根據模板的不同例項,實現不同型別的使用。
用乙個例**更好地理解
class a
;int main()
虛析構函式這裡我們先來清楚乙個問題,為什麼最好把父類的析構函式定義成虛函式呢?
#include
using
namespace
std;
class a
現象:給父類加上virtual後,會先析構子類的析構函式,再析構父類的析構函式。
分析:把父類的析構函式宣告成虛函式,這將使所有派生類的析構函式自動成為虛函式。這樣,如果想要顯式地通過delete刪除乙個物件,delete的操作物件用了指向派生類物件的基類指標,則會呼叫基類的析構函式。
探索虛函式表
通過一塊連續記憶體來儲存虛函式的位址。
正如上圖中監視顯示,虛函式表_vfptr中存放著虛函式fun1和fun2的位址。
單繼承有虛函式但是沒有重寫虛函式
通過監視視窗可以看到,父類中有乙個虛函式,父類的例項化物件中有乙個虛表指標和乙個成員變數,然後子類中有乙個函式,但不是虛函式,但為什麼子類的成員變數裡會有乙個虛表指標呢?因為它是從父類裡繼承而來的。需要說明的是,這個函式指標,指向的內容是父類的虛函式。
單繼承有虛函式有重寫虛函式
通過和上面的繼承虛函式相比,子類的虛函式表中的函式位址已經變成了子類的函式了。
探索單繼承物件模型
class base
;class derive:public base
;void test()
對於derive類來說,我們預想的是,它的虛表裡會有子類重寫父類的fun1,父類的fun2,子類的fun3和fun4.
但是,通過監視視窗可知只有fun1()和fun2()。這裡是因為編譯器的問題所以沒有顯示出fun3和fun4。
所以接下來我們需要實現乙個可以列印虛函式表的函式。
函式的實現:
這裡還有一點不好理解,就是傳參問題
探索多繼承的記憶體布局
學習了單繼承物件模型,接下來我們看看多繼承,同樣,通過**除錯觀察監視從而了解多繼承的記憶體布局。
class base1
;class base2
;class derive:public base1,public base2
;typedef
void(*func) ();
void printvtable(int* vtable)
cout
int main()
多繼承中有兩個虛函式表,分別是base1和base2的虛函式表,我們猜想子類裡的fun1()會覆蓋父類base1和base2中的fun1(),但是子類裡的fun3()會放在base1裡還是base2裡還是自己開闢乙個虛函式表呢?
接下來,我們通過監視視窗看看:
結果證實了子類裡的fun1()會覆蓋父類base1和base2中的fun1(),但是,同單繼承中出現的問題一樣,編譯器依舊無法在監視視窗中顯示出fun3()的情況。
所以,靠自己吧!
通過上圖的列印結果可知,fun3()存在於base1的虛函式表中。當涉及多繼承時,子類的虛函式會存放於先繼承的那個類的虛函式表裡。
多型 多型物件模型
1 什麼多型?當使用基類的指標或引用呼叫重寫的虛函式時,指向父類調的就是父類的虛函式,指向子類調的就是子類的虛函式。下面我們來看一段 sizeof aa 的結果為什麼會是8呢?這是因為函式fun1是乙個虛函式,函式內部存在乙個虛表指標。單繼承物件模型 由於編譯器做了一定的優化,子類中自己定義的函式在...
多型 多型物件模型
一 什麼是多型。物件導向語言有三大特點,封裝 繼承 多型。今天就討論一下多型,多型是 當使用基類的指標或引用呼叫重寫的虛函式時,當指向父類呼叫的就是父類的虛函式,當指向子類就是呼叫子類的虛函式。多型 多種形態。多型分為靜態多型和動態多型。實現多型的其中乙個條件必須是要把子類給給父類,要構成is a的...
多型 多型物件模型
理解多型 所謂多型,其實就是多種 形態 c 中虛函式的主要作用就是實現多型,簡單說父類的指標 引用呼叫重寫的虛函式,當父類指標 引用指向父類物件時呼叫的是父類的虛函式,指向子類物件時呼叫的是子類的虛函式。類別 1 編譯時的多型性。編譯時的多型性是通過過載來實現的。對於非虛的成員來說,系統在編譯時,根...