這點確實要注意,這個和delphi中是不一樣的,不過也可以理解成delphi的create函數並不等同於c++的構造函數。
using std::cout;
using std::endl;
using std::string;
class A
{
public:
A()
{
test();
}
protected:
virtual void test() const
{
cout << "A.test()" << endl;
}
};
class B : public A
{
public:
B()
{
}
protected:
virtual void test() const override
{
cout << "B.test()" << endl;
}
};
int main()
{
B b; // 將會調用A.test()
return 0;
}
上面代碼中在A的構造函數中調用了virtual函數test(),實際上執行的是父類的test而不是子類的test,雖然我們創建的是一個子類的對象,這是c++類構造的邏輯決定的:
在創建子類之前實際上先創建了一個父類,或者說在運行子類的構造函數之前,會先調用父類的構造函數,而在父類的構造函數運行期間,這個對象還是一個父類的對象,所以這時候這個對象根本不知道有子類,或者這麼說,就是這個對象的虛表指針實際上指向的是父類自己的虛表,所以導致調用的test實際上是父類自己的test,這個可以通過把虛表指針的地址打出來就能發現,而delphi的create函數沒有這個問題,即使是在父類的create調用虛函數,也能正常的展現多態特性。
析構函數同理。
總結:
在構造和析構期間不要調用virtual函數,因爲這類調用從不下降至derived class(比起當前執行構造函數和析構函數那層)