本文虽是起了个想要把C++中虚函数彻底透彻介绍的标题,但实际上只是本人记录虚函数一些要点的文章。
最近读了《Effective C++》,里面有几个关于虚函数的条款,以前对于虚函数不太了解,看了条款之后发现需要记录下来加深自己的印象。
多态基类的析构函数要为虚函数
这一点也正是多态的体现,假设有两个类Father,Son(举得例子不够经典….):
class Father
{
public:
Father (){};
virtual ~Father(){};
}
class Son: public Father
{
string sonName;
int *a;
public:
Son(string name):sonName(name)
{
a =new int[10];
};
~Son()
{
delete a;
}
}
假设有以下代码:
Son son;
Father *fa = &son;
delete fa;
若Father 类的析构函数不是虚函数,怎么不能实现动态绑定,从而只会调用父类Father的析构函数,而不会调用子类的析构函数,从而造成内存泄露….
构造函数不能为虚函数
同样还是上面的例子,假设我们构造一个son对象,构造函数执行的过程是(省略参数…) Father() Son() 但是根据虚函数的情况,若构造函数为虚函数,岂不是只执行了Son的构造函数,不执Father()的构造函数…….这跟构造原理也出现了矛盾,因此构造函数是不能成为虚函数的。
构造函数和析构函数中不要调用虚函数
上面的例子继续扩展:
class Father
{
public:
Father (){makeMoney();};
virtual ~Father(){};
virtual void makeMoney(){ cout<<"father make money"};
}
class Son: public Father
{
string sonName;
int *a;
public:
Son(string name):sonName(name)
{
a =new int[10];
makeMoney();
};
~Son()
{
delete a;
}
virtual void makeMoney(){ cout<<"son make money"};//函数进行了重写
}
int main()
{
Father *father = new Son();
delete father;
return 0;
}
上述代码在Father类构造函数中调用了虚函数makeMoney(),我们期望运行的结果是怎样的?(虽然看起来很奇怪…)
不管期望如何,实际的运行结果是这样的: “father make money”!也就是说此时构造函数中的虚函数makeMoney没有进行动态绑定。
运行构造函数和析构函数时,对象都是不完整的。同时在基类的构造函数和析构函数中,将派生类对象当成基类对象对待,因此结论就是此时运行的虚函数则是构造析构函数自身类定义的版本函数,无法进行动态绑定。