可以,但是达不到想要的效果,应该尽可能避免在构造函数和析构函数中调用虚函数。
class base{
public:
base(){
cout<<The size is size()<<endl;
}
private:
virtual size_t size(){
return sizeof(*this);
}
};
class derived : public class base{
public:
derived(){
cout<<The size of is size()<<endl;
}
private:
size_t size(){
return sizeof(*this);
}
};
当定义一个derived实例对象时,在base的构造函数中调用size()会被静态的决议为base::size()而不是derived::size()。
可以这么理解,当在构造base部分时,derived并不一个完整的实例对象,derived部分的成员变量甚至没有被初始化,如果在构造base期间调用的是derived的虚函数并且该虚函数引用了尚未构造好的成员变量,试想会发生什么。所以,从安全性考虑,经由构造中的对象来调用一个虚函数,其函数就是正在构造的对象的所属函数。
同时析构函数也如此。当正在析构base部分时,derived部分已经被析构完毕,成员变量已经无效,调用的虚函数是所属base的。
下面解释一下编译器是怎么做到的?
虚函数调用和实例对象的虚指针以及类的虚表有关。因此想要控制虚函数的调用,就必须控制虚指针的初始化。所以当一个实例对象正在构造base部分时,此时该实例的虚指针必须指向base类的虚表。那么虚指针何时被初始化,在程序员编写的代码之前或者是构造函数中初始化成员列表中所列的成员初始化操作之前。