-
class B{
-
public :
-
virtualvoid m1();
-
virtualvoid m2();
-
};
-
class D : public B{
-
virtualvoid m1();
-
}
C++的動態綁定使用vtable(虛成員函數表)來實現。vtable支持運行時查詢,使系統可以將某一函數名綁定到vtable的特定入口地址。
例如上段代碼的虛函數表為:
虛成員函數 入口地址 虛成員函數 入口地址
B::m1 0x7723 D::m1 0x99a7 //重定義的
B::m2 0x23b4 D::m2 0x23b4 //完全繼承
由於系統執行虛函數時,要從對象的vtable找到函數入口地址,而且vtable是存儲於對象的內存空間中。假如對象沒有實例化,就找不到vtable。因此,構造函數不能是vittual。
但是,析構函數一般都需要加上virtual,假如定義Base *b = new Deriver; Deriver是Base的子類,並且~Base()不為virtual。那么當對象被注銷時,系統只會調用~Base(),而不會調用~Deriver(),因為b是Base類型,已被靜態綁定析構函數。如果基類或子類用new創建了內存空間,就必須通過析構函數銷毀。因此必須使用vitual析構函數,實現動態綁定。
另外:從另一個角度也可以看出構造函數不能為虛函數,1,虛函數的作用在於通過父類的指針或者引用調用它的時候能夠變成調用子類的那個成員函數。而構造函數是在創建對象時自動調用的,不可能通過父類或者引用去調用,因此就規定構造函數不能是虛函數。
2,構造函數不需要是虛函數,也不允許是虛函數,因為創建一個對象時我們總是要明確指定對象的類型,盡管我們可能通過實驗室的基類的指針或引用去訪問它
但析構卻不一定,我們往往通過基類的指針來銷毀對象。這時候如果析構函數不是虛函數,就不能正確識別對象類型從而不能正確調用析構函數。