為什麼不能在建構函式中使用虛擬函式
阿新 • • 發佈:2019-02-19
先上程式碼:
// c_datastructure.cpp : 定義控制檯應用程式的入口點。 // #include "stdafx.h" #include<iostream> #include<string> using namespace std; class Base { public: Base() { fun(); } virtual void fun() { cout << "Base" << endl; } }; class A :public Base { public: A() :Base(), a(a) {} virtual void fun() { cout << "A" << endl; } private: int a; }; int main() { cout << "************" << endl; Base *a = new A; delete a; return 0; }
此時發揮作用的是Base:fun()而不是派生類A:fun(),也就是虛擬函式在建構函式中不起作用。當例項化一個派生類物件時,首先進行基類部分的構造,然後再進行派生類部分的構造。即建立A物件時,會先呼叫Base的建構函式,再呼叫A的建構函式。當在構造基類部分時,派生類還沒被完全建立,從某種意義上講此時它只是個基類物件。即當Base::fun()執行時A物件還沒被完全建立,此時它被當成一個Base物件,而不是A物件,因此fun繫結的是Base的fun
C++之所以這樣設計是為了減少錯誤和Bug的出現。假設在建構函式中虛擬函式仍然“生效”,即Base::fun()中的fun();所呼叫的是A::fun()。當Base::fun()被呼叫時派生類中的資料a還未被正確初始化,這時執行A::fun()將導致程式對一個未初始化的地址解引用,得到的結果是不可預料的,甚至是程式崩潰(訪問非法記憶體)。