1. 程式人生 > >為什麼不能在建構函式中使用虛擬函式

為什麼不能在建構函式中使用虛擬函式

先上程式碼:

// 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()將導致程式對一個未初始化的地址解引用,得到的結果是不可預料的,甚至是程式崩潰(訪問非法記憶體)。