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. 0124——KVC KVO模式

    1.KVC KVC是Key-Value-Coding的简称,它是一种可以直接通过字符串的名 字(key)来访问类属性(实例变量)的机制.而不是通过调用Setter.Getter方法访问.当使用KVO. ...

  2. Delphi线程同步

    总结一下Windows常用的几种线程同步技术. 1.Critical Sections(临界段),源代码中如果有不能由两个或两个以上线程同时执行的部分,可以用临界段来使这部分的代码执行串行化.它只能在 ...

  3. 从汇编看c++中含有虚基类对象的析构

    c++中,当继承结构中含有虚基类时,在构造对象时编译器会通过将一个标志位置1(表示调用虚基类构造函数),或者置0(表示不调用虚基类构造函数)来防止重复构造虚基类子对象.如下图菱形结构所示: 当构造类B ...

  4. 【Lucene4.8教程之五】Luke

    一.Luke基本内容 1.Luke简介 Luke可用于查看Lucene创建的索引,并对其进行基本操作. 2.创建Luke (1)从Github上下载源文件 https://github.com/tar ...

  5. javascript 实现禁止右键,复制,选取文本 (兼容firefox,IE,chrome等主流浏览器)

    1. JS 禁止右键 <script type="text/javascript">document.oncontextmenu=function(e){return ...

  6. CI框架微信开发-自定义菜单

    在CI框架下面实现了自定义菜单功能.写了一个model,一个类库.顺便附带access_token的实现方式 <?php class Makemenu{ public $menustr; pub ...

  7. 像asp.net Mvc一样开发nodejs+express Mvc站点

    像asp.net Mvc一样开发nodejs+express Mvc站点 首先,我是个c#码农.从事Mvc开发已然4个年头了,这两年前端MVC的兴起,我也跟风学了一些,对前端的框架也了解一些,angu ...

  8. 关于文字颜色/图片背景---selector状态列表

    文字颜色 android:textColor="@style/style_name" ----------------------------------widget 图片背景 a ...

  9. 杀死MySQL的连接

    命令  kill 执行线程号 C# 执行杀死指定的连接 1  强制Kill掉 internal protected void KillConnection(MySqlConnection c) { i ...

  10. 【Xamarin挖墙脚系列:IOS现有的设备SDK /OS/硬件一览】

    附件下载: http://pan.baidu.com/s/1o7rsrUE