小心在构造函数或者析构函数中调用虚函数

作者: veaxen 分类: C/C++ 发布时间: 2017-04-07 23:54

这个问题来自于《Effective C++》条款9:永远不要在构造函数或析构函数中调用虚函数 。

之所以说小心,是因为一般建议我们不要在构造函数或者析构函数中调用“虚函数”,因为在构造函数或者析构函数中,虚函数的机制并不会被执行,下面我们来分析分析。

构造函数中的虚函数

假设有如下的代码

#include <iostream>

class A
{
public:
    A(){doSth()};
    virtual void doSth(){printf("This is A");}
}
class B:public A
{
public:
    virtual void doSth(){printf("This is B");}
}

int main()
{
    B b;
    return 0;
}

执行结果是:
This is A

分析:
在构造函数中,虚拟机制不会发生作用,因为基类的构造函数在派生构造函数之前执行,当基类构造函数执行时,派生类数据成员还没有被初始化。如果基类构造期间调用虚函数向下匹配到派生类,派生类的函数理所应当会涉及派生类本身的数据成员,但是那些数据成员还没有被初始化(因为派生类的构造函数还没有被调用,是先调用基类的构造函数),因此,C++不允许在构造函数中执行虚拟机制,而是直接执行基类的函数。

析构函数中的虚函数

看了构造函数中使用虚函数的分析,可以类比知道为什么虚函数中也不能使用虚函数的机制:
当一个子类析构时,是先析构子类,再析构父类,也就是先调用子类的析构函数,再调用父类的析构函数,那么如果虚机制可以在析构函数中被使用,那么当调用父类的析构函数时,在析构中调用虚函数,而虚函数是可能被子类重写了的,涉及到了子类的数据成员,而在这之前,子类的数据成员已经析构了,所以这样就产生非法行为了。因此,析构函数中的虚函数也是没有起到虚函数的作用的。

总结

一般情况下,应该避免在构造函数和析构函数中调用虚函数,如果一定要这样做,程序猿必须清楚,这是对虚函数的调用其实是实调用

如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!

发表评论

电子邮件地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据