必威体育Betway必威体育官网
当前位置:首页 > IT技术

析构函数写成virtual的好处

时间:2019-10-05 13:13:27来源:IT技术作者:seo实验室小编阅读:65次「手机版」
 

析构函数

相信学习c++的很多同志都听过这样的建议:最好将类的析构函数写成虚函数,如下:
class B
{
public:
    B() { printf("B()\n"); }
    virtual ~B() { printf("~B()\n"); }
private:
    int m_b;
};

这么写到底有什么好处呢?

我们通过示例给大家解释,示例1,析构函数为普通函数

//示例1
class B
{
public:
    B() { printf("B()\n"); }
    ~B() { printf("~B()\n"); }
private:
    int m_b;
};

class D : public B
{
public:
    D() { printf("D()\n"); }
    ~D() { printf("~D()\n"); }
private:
    int m_d;
};

int main()
{
    B* pB = new D();
    delete pB;
    
    return 0;
}

运行结果如下(先不要看结果自己思考一下看看结果和你思考的是否相同):

图1

我们再看示例2,析构函数为虚函数

//示例2
class B
{
public:
    B() { printf("B()\n"); }
    virtual ~B() { printf("~B()\n"); }
private:
    int m_b;
};

class D : public B
{
public:
    D() { printf("D()\n"); }
    ~D() { printf("~D()\n"); }
private:
    int m_d;
};

int main()
{
    B* pB = new D();
    delete pB;
    
    return 0;
}

运行结果如下(先不要看结果自己思考一下看看结果和你思考的是否相同):

图2

看到不同了吗?没错,示例2中调用了子类D的析构函数~D(),而示例1中没有调用子类D的析构函数~D()。为什么会这样呢?

原因是:示例1中,我们删除掉父类B的指针pB,因为编译器知到pB是类B的指针,所以会调用类B的析构函数去释放空间,而对于示例2,我们删掉父类B的指针pB,但是pB指向的是子类D的对象,通过虚函数表,编译器知道要去执行子类D的析构函数~D(),执行完子类的析构函数后,按照c++的内部机制紧接着会去执行父类的析构函数,所以我们看到了如图2的执行结果。

注:c++中有这样的约束:执行子类构造函数之前一定会执行父类的构造函数;同理,执行子类的析构函数后,一定会执行父类的析构函数,这也是为什么我们一直建议类的析构函数写成虚函数的原因。

相关阅读

java中的析构函数

乍一看,java里面怎么还有这样的词语。其实:析构函数(destructor) 与  构造函数 相反,当对象结束其 生命周期时(例如对象所在的函数

构造函数和析构函数

通过C++ Primer重新回顾构造函数和析构函数,发现真的好多都忘了… 构造函数 类的构造函数是类的一种特殊的成员函数,它会在每次

分享到:

栏目导航

推荐阅读

热门阅读