先看一個例子:
#include <iostream> using namespace std; class A{ public: A() { show(); } virtual void show(){ cout<<"in A"<<endl; } virtual ~A(){ show(); } }; class B:public A{ public: B() { show(); } void show(){ cout<<"in B"<<endl; } }; int main(){ A *a = new A; delete a; cout << "*****************" << endl; A *b = new B; delete b; }
輸出結果,可以看到沒有預想的多態效果:
in A
in A
*****************
in A
in B
in A
結論:構造函數和析構函數調用虛函數時都不使用動態聯編,如果在構造函數或析構函數中調用虛函數,則運行的是為構造函數或析構函數自身類型定義的版本。
原因分析:
(1)不要在構造函數中調用虛函數的原因:因為父類對象會在子類之前進行構造,此時子類部分的數據成員還未初始化, 因此調用子類的虛函數是不安全的,故而C++不會進行動態聯編。
(2)不要在析構函數中調用虛函數的原因:析構函數是用來銷毀一個對象的,在銷毀一個對象時,先調用子類的析構函數,然后再調用基類的析構函數。所以在調用基類的析構函數時,派生類對象的數據成員已經“銷毀”,這個時再調用子類的虛函數已經沒有意義了。