建構函式不能聲明為虛函數的原因:
1,所謂虛函數就是多態情況下只執行一個,而從繼承的概念來講,總是先構造父類對象,然後才能使子類對象,如果建構函式設為虛函數,那麼你在構造父類的建構函式時就不得不顯式的調用構造,還有一個原因就是為了防錯誤的發生,試想如果你在子類中一不小心重寫了個跟父類建構函式一樣的函數,那麼你的父類建構函式將被覆蓋,也即不能完成父類的構造,就會出錯。
class A
{
public :
virtual A()
{
cout<<"A"<<endl;
}
};
class B: public A
{
public:
B()
{
cout<<"B"<<endl;
}
};
在編譯處,便已經提示無法通過,將virtual去掉
2,虛函數的主要意義在於被衍生類別繼承從而產生多態,衍生類別的建構函式中,編譯器會加入構造基類的代碼,如果基類的建構函式用到了參數,則衍生類別在其建構函式中必須為基類給出參數,就是這個原因,原因有點繞,就是說如果衍生類別的建構函式必須跟父類一摸一樣,這顯然是不符合實際的
當然還有其他的解釋:1,從儲存空間角度,虛函數對應一個vtable,可是這個vtable其實是儲存在對象的記憶體空間的。問題出來了,如果建構函式是虛的就需要通過vtable來調用,可是對象還沒有執行個體化,也就是記憶體空間還,沒有,無法找到vtable,所以建構函式不能為虛函數。
2,從使用角度 虛函數主要用於在資訊不全的情況下,能使重載的函數得到對應的調用。建構函式本身就是要初始化執行個體,那使用虛函數也就沒有執行個體意義了,最開始的執行個體都沒有初始化,何來多態呢。虛函數的作用於通過父類的指標或者引用來調用它的時候能夠變成調用子類的那個成員函數。而建構函式實在建立對象的時候自動調用的,不可能通過父類的指標或引用去調用,因此規定建構函式不能為虛函數。
3,從實現上看,vtable在建構函式調用後才建立,因而建構函式不可能為虛函數,從實際含義上看,在調用建構函式時還不能確定對象的真實類型(子類要調用父類的建構函式),而且建構函式提供初始化,對象生命期只執行一次,不是對象的動態行為,也沒有太大必要成為虛函數。