可以,但是要小心。它可能不象你期望的那樣工作。在構(gòu)造函數(shù)中,虛擬調(diào)用機(jī)制不起作用,因?yàn)槔^承類的重載還沒有發(fā)生。對(duì)象先從基類被創(chuàng)建,“基類先于繼承類(base before derived)”。
看看這個(gè):
#include
#include
using namespace std;
class B {
public:
B(const string& ss) { cout << "B constructor\n"; f(ss); }
virtual void f(const string&) { cout << "B::f\n";}
};
class D : public B {
public:
D(const string & ss) :B(ss) { cout << "D constructor\n";}
void f(const string& ss) { cout << "D::f\n"; s = ss; }
private:
string s;
};
int main()
{
D d("Hello");
}
程序編譯以后會(huì)輸出:
B constructor
B::f
D constructor
注意不是D::f。設(shè)想一下,如果出于不同的規(guī)則,B::B()可以調(diào)用D::f()的話,會(huì)產(chǎn)生什么樣的后果:因?yàn)闃?gòu)造函數(shù)D::D()還沒有運(yùn)行,D::f()將會(huì)試圖將一個(gè)還沒有初始化的字符串s賦予它的參數(shù)。結(jié)果很可能是導(dǎo)致立即崩潰。
析構(gòu)函數(shù)在“繼承類先于基類”的機(jī)制下運(yùn)行,因此虛擬機(jī)制的行為和構(gòu)造函數(shù)一樣:只有本地定義(local definitions)被使用——不會(huì)調(diào)用虛擬函數(shù),以免觸及對(duì)象中的(現(xiàn)在已經(jīng)被銷毀的)繼承類的部分。
更多的細(xì)節(jié),參見《C++語言的設(shè)計(jì)和演變》13.2.4.2和《C++程序設(shè)計(jì)語言》15.4.3。
有人暗示,這只是一條實(shí)現(xiàn)時(shí)的人為制造的規(guī)則。不是這樣的。事實(shí)上,要實(shí)現(xiàn)這種不安全的方法倒是非常容易的:在構(gòu)造函數(shù)中直接調(diào)用虛擬函數(shù),就象調(diào)用其它函數(shù)一樣。但是,這樣就意味著,任何虛擬函數(shù)都無法編寫了,因?yàn)樗鼈冃枰揽炕惖墓潭ǖ膭?chuàng)建(invariants established by base classes)。這將會(huì)導(dǎo)致一片混亂。
看看這個(gè):
#include
#include
using namespace std;
class B {
public:
B(const string& ss) { cout << "B constructor\n"; f(ss); }
virtual void f(const string&) { cout << "B::f\n";}
};
class D : public B {
public:
D(const string & ss) :B(ss) { cout << "D constructor\n";}
void f(const string& ss) { cout << "D::f\n"; s = ss; }
private:
string s;
};
int main()
{
D d("Hello");
}
程序編譯以后會(huì)輸出:
B constructor
B::f
D constructor
注意不是D::f。設(shè)想一下,如果出于不同的規(guī)則,B::B()可以調(diào)用D::f()的話,會(huì)產(chǎn)生什么樣的后果:因?yàn)闃?gòu)造函數(shù)D::D()還沒有運(yùn)行,D::f()將會(huì)試圖將一個(gè)還沒有初始化的字符串s賦予它的參數(shù)。結(jié)果很可能是導(dǎo)致立即崩潰。
析構(gòu)函數(shù)在“繼承類先于基類”的機(jī)制下運(yùn)行,因此虛擬機(jī)制的行為和構(gòu)造函數(shù)一樣:只有本地定義(local definitions)被使用——不會(huì)調(diào)用虛擬函數(shù),以免觸及對(duì)象中的(現(xiàn)在已經(jīng)被銷毀的)繼承類的部分。
更多的細(xì)節(jié),參見《C++語言的設(shè)計(jì)和演變》13.2.4.2和《C++程序設(shè)計(jì)語言》15.4.3。
有人暗示,這只是一條實(shí)現(xiàn)時(shí)的人為制造的規(guī)則。不是這樣的。事實(shí)上,要實(shí)現(xiàn)這種不安全的方法倒是非常容易的:在構(gòu)造函數(shù)中直接調(diào)用虛擬函數(shù),就象調(diào)用其它函數(shù)一樣。但是,這樣就意味著,任何虛擬函數(shù)都無法編寫了,因?yàn)樗鼈冃枰揽炕惖墓潭ǖ膭?chuàng)建(invariants established by base classes)。這將會(huì)導(dǎo)致一片混亂。

