1、原因:

   在实现多态时, 当用基类指针操作派生类, 在析构时候防止只析构基类而不析构派生类。

2、例子:

  (1)、

    

  #include<iostream>
  using namespace std;
  class Base{
  public:
      Base() {};
      ~Base() {cout << "Output from the destructor of class Base!" << endl;};

      void DoSomething() { cout << "Do something in class Base!" << endl; };
  };

  class Derived : public Base{
  public:
      Derived() {};
      ~Derived() { cout << "Output from the destructor of class Derived!" << endl; };

      void DoSomething() { cout << "Do something in class Derived!" << endl; };
  };
   int   main(){
      Derived* p =  new Derived;
      p->DoSomething();
      delete p;
      return 0;
   }  

  运行结果:

  Do something in class Derived!

  Output from the destructor of class Derived!

  Output from the destructor of class Base!

  代码中基类的析构函数不是虚函数,在main函数中用继承类的指针去操作继承类的成员,释放指针P的过程是:先释放继承类的资源,再释放基类资源。

  (2)、

    #include<iostream>

  using namespace std;
  class Base{
  public:
      Base() {};
      ~Base() {cout << "Output from the destructor of class Base!" << endl;};

      void DoSomething() { cout << "Do something in class Base!" << endl; };
  };

  class Derived : public Base{
  public:
      Derived() {};
      ~Derived() { cout << "Output from the destructor of class Derived!" << endl; };

      void DoSomething() { cout << "Do something in class Derived!" << endl; };
  };
   int   main(){
      Base* p =  new Derived;
      p->DoSomething();
      delete p;
      return 0;
   }

  

    运行结果:

    Do something in class ClxBase!
    Output from the destructor of class ClxBase!

  代码中基类的析构函数同样不是虚函数,不同的是在main函数中用基类的指针去操作继承类的成员,释放指针P的过程是:只释放基类的资源,而没有调用继承类的析构函数。 调用DoSomething()函数执行的也是基类定义的函数。

  一般情况下,这样的删除只能够删除基类对象,而不能删除子类对象,形成了删除一半形象,造成内存泄漏。

      在公有继承中,基类对派生类及其对象的操作,只能影响到那些从基类继承下来的成员。如果想要用基类对非继承成员进行操作,则要把基类的这个函数定义为虚函数。 析构函数自然也应该如此:如果它想析构子类中的重新定义或新的成员及对象,当然也应该声明为虚的。

   (3)、

  #include<iostream>
  using namespace std;
  class Base{
  public:
      Base() {};
      virtual ~Base() {cout << "Output from the destructor of class Base!" << endl;};

      virtual void DoSomething() { cout << "Do something in class Base!" << endl; };
  };

  class Derived : public Base{
  public:
      Derived() {};
      ~Derived() { cout << "Output from the destructor of class Derived!" << endl; };

      void DoSomething() { cout << "Do something in class Derived!" << endl; };
  };
   int   main(){
      Base* p =  new Derived;
      p->DoSomething();
      delete p;
      return 0;
   }

  运行结果:

    Do something in class ClxDerived!
    Output from the destructor of class ClxDerived!
    Output from the destructor of class ClxBase!

代码中基类的析构函数被定义为虚函数,在main函数中用基类的指针去操作继承类的成员,释放指针P的过程是:释放了继承类的资源,再调用基类的析构函数。调用DoSomething()函数执行的也是继承类定义的函数。

3、总结:

  基类指针可以指向派生类的对象(多态性),如果删除该指针delete p;就会调用该指针指向的派生类析构函数,而派生类的析构函数又自动调用基类的析构函数,这样整个派生类的对象完全被释放。如果析构函数不被声明成虚函数,则编译器实施静态绑定,在删除基类指针时,只会调用基类的析构函数而不调用派生类析构函数,这样就会造成派生类对象析构不完全。所以,将析构函数声明为虚函数是十分必要的。

 

C++ 析构函数为虚函数的更多相关文章

  1. C++中为什么构造函数不能是虚函数,析构函数是虚函数

    一, 什么是虚函数? 简单地说,那些被virtual关键字修饰的成员函数,就是虚函数.虚函数的作用,用专业术语来解释就是实现多态性(Polymorphism),多态性是将接口与实现进行分离:用形象的语 ...

  2. 转 C++构造函数、析构函数、虚函数之间的关系

    C++构造函数.析构函数.虚函数之间的关系 1. 如果我们定义了一个构造函数,编译器就不会再为我们生成默认构造函数了.2. 编译器生成的析构函数是非虚的,除非是一个子类,其父类有个虚析构,此时的函数虚 ...

  3. C++中继承 声明基类析构函数为虚函数作用,单继承和多继承关系的内存分布

    1,基类析构函数不为虚函数 #include "pch.h" #include <iostream> class CBase { public: CBase() { m ...

  4. C++ 构造函数、析构函数与虚函数的关系

    编译环境:windows 10 + VS2105 1.构造函数不能为虚函数 虚函数的作用是为了实现C++多态机制.基类定义虚函数,子类可以重写该虚函数.当子类重写父类虚函数后,父类指针指向子类地址时, ...

  5. C++析构函数定义为虚函数(转载)

    转载:http://blog.csdn.net/alane1986/article/details/6902233 析构函数执行时先调用派生类的析构函数,其次才调用基类的析构函数.如果析构函数不是虚函 ...

  6. 【转】C++析构函数为什么要为虚函数

    注:本文内容来源于zhice163博文,感谢作者的整理. 1.为什么基类的析构函数是虚函数? 在实现多态时,当用基类操作派生类,在析构时防止只析构基类而不析构派生类的状况发生. 下面转自网络:源地址  ...

  7. 从零开始学C++之虚函数与多态(一):虚函数表指针、虚析构函数、object slicing与虚函数

    一.多态 多态性是面向对象程序设计的重要特征之一. 多态性是指发出同样的消息被不同类型的对象接收时有可能导致完全不同的行为. 多态的实现: 函数重载 运算符重载 模板 虚函数 (1).静态绑定与动态绑 ...

  8. 从零开始学C++之虚函数与多态(二):纯虚函数、抽象类、虚析构函数

    一.纯虚函数 虚函数是实现多态性的前提 需要在基类中定义共同的接口 接口要定义为虚函数 如果基类的接口没办法实现怎么办? 如形状类Shape 解决方法 将这些接口定义为纯虚函数 在基类中不能给出有意义 ...

  9. C++析构函数为什么要为虚函数

    注:本文内容来源于zhice163博文,感谢作者的整理. .为什么基类的析构函数是虚函数? 在实现多态时,当用基类操作派生类,在析构时防止只析构基类而不析构派生类的状况发生. 下面转自网络:源地址 h ...

随机推荐

  1. mvc原理和mvc模式的优缺点

    一.mvc原理   mvc是一种程序开发设计模式,它实现了显示模块与功能模块的分离.提高了程序的可维护性.可移植性.可扩展性与可重用性,降低了程序的开发难度.它主要分模型.视图.控制器三层. 1.模型 ...

  2. Qt Creator下载

    Qt官网 http://qt.digia.com qt的历史版本可以到http://download.qt-project.org/archive/qt/下载

  3. (原)ubuntu16中简单的使用google的protobuf

    转载请注明出处: http://www.cnblogs.com/darkknightzh/p/5804395.html 参考网址: http://www.cnblogs.com/luosongchao ...

  4. 前端学习书籍大全 包含PDF地址

    JavaScript类: javascript高级程序设计 pdf下载 ---->教程 javascript权威指南 pdf下载  ---->教程 javascript基础教程 pdf下载 ...

  5. js控制浏览器后退

    <script type="text/javascript"> window.history.forward(1); </script>

  6. python笔记之提取网页中的超链接

    python笔记之提取网页中的超链接 对于提取网页中的超链接,先把网页内容读取出来,然后用beautifulsoup来解析是比较方便的.但是我发现一个问题,如果直接提取a标签的href,就会包含jav ...

  7. python bottle 框架开发任务管理系统 V_1.0版

    经过1-2个星期的开发,现在开发了个半成品(UI现在比较烂,因为我的前端本来就很差,将就下吧),大概功能如下:用户功能(添加.删除.修改),添加部门功能,任务管理功能(添加.删除.修改,详细).项目管 ...

  8. LINUX SSH客户端的中文乱码问题

       原因在于文件/etc/sysconfig/i18n 这个文件是系统的区域语言设置, i18n是 国际化internationalization的缩写 i和n之间正好18个字母 解释: LANG= ...

  9. Ext4报错Uncaught Ext.Loader is not enabled

    提示: Uncaught Ext.Loader is not enabled, so dependencies cannot be resolved dynamically. Missing requ ...

  10. Qt 文件搜索(写入文本文件)

    代码无意间在网上找到,下载回来后改了几个格式,编译后经测试可以正常使用,这个个文件搜索的很好的例子,有两种搜索方式:一种是按文件名作为关键字进行搜索,一种是以文档中所包含的关键字进行搜索,贴两张图先: ...