C++:虛表指針、虛表、虛函數和動態多態
class Base { public: virtual void show() { std::cout << "Base show" << std::endl; } }; class Derived_1 : public Base { public: void show() override { std::cout << "Derived show" << std::endl; } }; class Derived_2: public Base { public: void show() override { std::cout << "Derived show" << std::endl; } }; Base *b = new Derived_1();
b->show(); Base *c = new Derived_2();
c->show();
分析上面代碼,用基指針b指向Derived_1的實例化對象,然后使用b調用Derived的實例化對象重寫的虛函數show(),同樣的創建另外一個基指針調用DErived_2的實例化對象然后調用其重寫的show()
那么有個問題,一樣時基類Base的指針,它是怎么知道我此時該調用的是Derive_1中的show()還是Derive_2中的show()?
找一個"地圖"用來查詢,這個"地圖"就放在Derived_1和Derived_2類的里面作為它們的成員之一,上面記錄著他們各自內部所有的虛函數地址
當調用
b->show();
時,會訪問Derived_1中的"地圖",找到屬于Derived_1的show()函數的地址,然后執行,c->show();同理。
這里的"地圖"就是虛表,虛表是一個指針數組,里面存放著該類所有虛函數的地址。
顯然,每個類都有自己不同的虛表,那基類指針b是如何得到對應不同的虛表?
當使用多態指針進行類的實例化時,就會"得到"地圖,每個基類內都有個成員,稱之為虛表指針,
當執行
Base *b = new Derived_1();
時,b的虛表指針就會初始化為Derived_1實例化對象的虛表地址,或者說指向虛表,這樣一來就可以通過虛表指針找到虛表,再進一步找到需要的虛函數
然后就是一個比較重要的問題:為什么必須是指針或者引用才能實現多態?
這里引用一篇博客的實驗
簡單來說,通過前面的闡述,我們知道多態是通過虛表指針、虛表進行索引查找子類的虛函數,
而賦值方式沒辦法對多態指針(基類指針)進行初始化,也就是說,以下面這種方式
Base b;
Derived_1 bb;
b = bb;
b內的虛表指針是不會指向bb的虛表,自然無法通過b去調用bb的show函數
浙公網安備 33010602011771號