虛函實現原理

對於含有虛函數的類,編譯器會自動爲其生成一個一維的虛函數表vtable,用來存儲虛函數的入口地址。然後在實例化類對象的時候,會自動創建一個指向該類虛函數表的指針vptr。

       當一個子類繼承父類(含虛函數)時,會賦值一個相同的虛函數表。然後如果子類中對父類中的虛函數進行重寫(注意:兩個函數的函數名、函數標籤都相同時纔算同一個函數),那麼就會再開闢一片空間來存儲重寫過的函數,子類的vtable中相應的入口地址也會被修改成這個重寫函數的入口地址。

       

class A
{
public:
	int a,b;
	void fun1(){...};
        void fun2(){...};
	virtual void virfun1(){...};// 假設存儲該函數的地址爲1
	virtual void virfun2(){...};//假設存儲該函數的地址爲2
};
class B public:A
{
public:
        int c;
	virtual void virfun1(){xxxxxx};//假設存儲該函數的地址爲3.
};

<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">        在某一類的具體實例中,內存中只保存了該實例的狀態變量(成員變量)以及一個指向該類虛函數表的指針vptr,而沒有成員函數。對於非虛函數,是在編譯時編譯器自動爲成員函數綁定入口地址的,而虛函數則要在運行時動態綁定(查水錶!。。好吧,是虛函數表。。)</span>

       上面一段代碼中,A類中,假設virfun1對應的地址爲1,virfun2對應的虛函數表爲2, 則 虛函數應該是 1,2。 然後B類, 由於重寫了virfun1(假設地址爲3),其虛函數表應該是3,2。 


     另外,在虛函數通常是方便指針變量的使用的, 比如:

   A* p = new B;
     這個在下一篇文章 ,虛函數&繼承 中會說到。。;

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章