为什么要用虚析构函数

原创 2015年07月15日 17:57:48

1 问题引出:为什么要使用虚析构函数?

class A //父亲
{
public:
    ~A()
    {
        cout << "调用了父亲的析构函数"<<endl;
    }
};

class B : public A  //儿子
{
public:
    ~B()
    {
        cout << "调用了儿子的析构函数" << endl;
    }
};

int main()
{
    A *p;
    p = new B;
    delete p; 
    system("pause");
    return 0;
}

运行结果:
这里写图片描述

 我们知道在delete p; 中 delete 操作符,会调用对象的析构函数,但是这里传入的是父类对象指针,所以delete 此时并不知道应该调用哪个析构函数,保险起见则只调用父类的析构函数,也就是说如果没有使用虚析构函数,那么一般情况下只会去析构父类,而不会去析构子类。所以当delete p; 的时候,就会发生内存泄漏,也从而产生了异常。

注:
上面是传入父类指针并对其直接析构,如果不是对父类指针(或者引用)直接析构那一般不会出错,如 void main() {B b;A *p;p=&c;} 这时虽然使用了父类指针,但不是对父类指针析构,而是很明确直接析构b,所以用不用虚函数,也可以正确析构,
如果某个类不包含虚函数,那一般是表示它将不作为一个基类来使用。当一个类不准备作为基类使用时,使析构函数为虚一般是个坏主意。因为它会为类增加一个虚函数表,使得对象的体积翻倍,还有可能降低其可移植性。
所以基本的一条是:无故的声明虚析构函数和永远不去声明一样是错误的。实际上,很多人这样总结:当且仅当类里包含至少一个虚函数的时候才去声明虚析构函数。

2 那使用虚析构函数会有什么效果?
我们把析构函数前加上virtual关键字,来看一下效果。

class A //父亲
{
public:
    virtual ~A()
    {
        cout << "调用了父亲的析构函数"<<endl;
    }
};

class B : public A  //儿子
{
public:
    ~B()
    {
        cout << "调用了儿子的析构函数" << endl;
    }
};

int main()
{
    A *p;
    p = new B;
    delete p; 
    system("pause");
    return 0;
}

运行结果如下:
这里写图片描述

在使用虚析构函数后,delete 明显变聪明了,知道应该先析构儿子,再去析构父亲了。但是在B类(儿子类)的析构函数刻意没有加 virtual 关键字,可见如同其他虚函数一样,只要父类加 virtual 就可以了。

引申:
虚析构函数,也是通过vftable来实现的,实际上当父类的析构函数声明为虚函数时,子类的析构函数也变成了虚函数(虽然两者函数名不同),即告诉编译器,我和我的派生类都需要动态(运行时)完成析构函数执行。

在编译器中我们可以看到:
这里写图片描述
析构函数的名字做了特殊处理,换成了‘vector deleting destructor’,用特定的标记,来标明析构函数。所以即使函数名不同,只要父类中使用 virtual ,也可以是所有子类的析构函数变成虚函数。

注:
为了方便对比,现给出包含多个虚函数的虚函数表,如下:
这里写图片描述

版权声明:本文为博主原创文章,未经博主允许不得转载。

构造函数为什么不能为虚函数 & 基类的析构函数为什么要为虚函数

一、构造函数为什么不能为虚函数 1. 从存储空间角度,虚函数对应一个指向vtable虚函数表的指针,这大家都知道,可是这个指向vtable的指针其实是存储在对象的内存空间的。问题出来了,如果构造函数...
  • yusiguyuan
  • yusiguyuan
  • 2014年08月09日 09:37
  • 1062

C++中基类的析构函数为什么要用virtual虚析构函数

C++中基类的析构函数为什么要用virtual虚析构函数, 弄清楚为什么。
  • IIcyZhao
  • IIcyZhao
  • 2013年09月22日 18:41
  • 4623

为什么要用虚函数?什么时候用虚函数?

刚开始学C++学到“类”这一章的时候一直不明白虚函数用来做什么。看书上举的例子不太明白。 #include using namespace std; class Father { public: ...
  • CharlesSimonyi
  • CharlesSimonyi
  • 2013年04月16日 22:25
  • 5572

什么时候要用虚析构函数?

什么时候要用虚析构函数? 通过基类的指针来删除派生类的对象时,基类的析构函数应该是虚的。否则其删除效果将无法实现。 一般情况下,这样的删除只能够删除基类对象,而不能删除子类对象,形成了删除一半形象...
  • rock_joker
  • rock_joker
  • 2017年05月27日 13:20
  • 110

为什么要用“虚析构函数”?

析构函数的工作方式是:       最底层的派生类(most   derived   class)的析构函数最先被调用,然后调用每一个基类的析构函数。       因为在C++中,当一个派生类...
  • jomdd
  • jomdd
  • 2011年10月24日 14:58
  • 468

什么时候要用虚析构函数?

什么时候要用虚析构函数?       通过基类的指针来删除派生类的对象时,基类的析构函数应该是虚的。否则其删除效果将无法实现。       一般情况下,这样的删除只能够删除基类对象,而不能删除子类对象...
  • fu_zk
  • fu_zk
  • 2013年08月05日 23:42
  • 966

虚析构函数示例

  • 2012年02月07日 11:26
  • 472B
  • 下载

虚基类 虚函数成员 虚析构函数

  • 2013年12月26日 23:03
  • 2KB
  • 下载

C++虚基类 虚函数 虚析构函数

  • 2013年12月07日 15:00
  • 725B
  • 下载

C++继承中的虚析构函数

看看下面程序有什么错误: #include using namespace std; class Father { public: Father(){}; ~Father()...
  • yangyangye
  • yangyangye
  • 2015年04月16日 15:42
  • 460
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:为什么要用虚析构函数
举报原因:
原因补充:

(最多只允许输入30个字)