• c++之——虚析构函数


    先看代码:

      1 #include<iostream>
      2 using namespace std;
      3 
      4 class Parent {
      5 public:
      6     Parent() :a(100), b(200), c(300)
      7     {
      8         
      9         p = new char[10];
     10         //strcpy(p, "abc");
     11         cout << "parent 无参构造。。。
    ";
     12     }
     13     Parent(int test) :a(1000), b(2000), c(3000)
     14     {
     15         p = new char[10];
     16         //strcpy(p, "abc");
     17         cout << "parent 有参构造。。。
    ";
     18     }
     19     ~Parent()
     20     {
     21         delete[] p;
     22         cout << "Parent 析构。。。
    ";
     23     }
     24     int a;
     25     int b;
     26     int c;
     27     char *p;
     28     void p_print()
     29     {
     30         cout << "a b c is" << a << " " << b << " " << c << endl;
     31     }
     32 
     33 };
     34 class Child1 :  public Parent
     35 {
     36 public:
     37     Child1() :Parent(1),a(10), b(0), c(0) 
     38     { 
     39         p = new char[10];
     40     //    strcpy(p, "abc");
     41         cout << "child1 构造
    ";
     42     }
     43     ~Child1()
     44     {
     45         delete[] p;
     46         cout << "child1 析构,,,
    ";
     47     }
     48     void c1_print()
     49     {
     50         cout << "a b c is" << a << " " << b << " " << c << endl;
     51     }
     52 
     53     int a;
     54     int b;
     55     int c;
     56     char *p;
     57 };
     58 class Child2 :  public Child1
     59 {
     60 public:
     61     Child2() :Child1(), b(2), c(3) 
     62     { 
     63         p = new char[10];
     64         //strcpy(p, "abc");
     65         cout << "child2 构造
    "; 
     66     }
     67     ~Child2()
     68     {
     69         delete[] p;
     70         cout << "child2 析构,,,
    ";
     71     }
     72     void c2_print()
     73     {
     74         cout << "a b c is" << Parent::a << " " << b << " " << c << endl;
     75     }
     76     //int a;
     77     int b;
     78     int c;
     79     char *p;
     80 };
     81 /*
     82 class Child3 : public Child1, public Child2
     83 {
     84 public:
     85     Child3() : Child1(), Child2(), b(20), c(30) { cout << "child 构造
    "; }
     86     ~Child3()
     87     {
     88         cout << "child 析构,,,
    ";
     89     }
     90     void c3_print()
     91     {
     92         cout << "a b c is" << a << " " << b << " " << c << endl;
     93     }
     94     //int a;
     95     int b;
     96     int c;
     97 };
     98 */
     99 void play()
    100 {
    101     Child2* c2 = new Child2;
    102     delete c2;
    103 }
    104 int main()
    105 {
    106     //Child2* c2 = new Child2;
    107     play();
    108     return 0;
    109 }

    这样是没问题的(c++编译器会以构造相反的顺序执行析构函数),但是,在很多时候,我们不能在调用函数末尾就delete掉这个内存,还需要和后续交互。比如作为函数参数,为了实现多态,我们函数参数是父类的指针,所以更常见和一般的设计思维是更改paly和main函数如下:

     1 void play(Parent* p)
     2 {
     3     delete p;
     4 }
     5 int main()
     6 {
     7     Child2* c2 = new Child2;
     8     play(c2);
     9     return 0;
    10 }

    运行结果显示内存泄漏了,只析构了父类;所以我们有那么一种需求,要想和多态的效果一样,传什么指针去,自动析构应该析构的东西,更改代码,实现虚析构函数。

    只用更改基类的析构函数,加上virtual关键字:

    1     virtual ~Parent()
    2     {
    3         delete[] p;
    4         cout << "Parent 析构。。。
    ";
    5     }

    这样就没有内存泄漏了。

    知识简要:

     如果基类的析构函数不是虚函数,则delete一个指向派生类对象的基类指针将产生未定义的行为。之前我们介绍过一个准则,如果一个类需要析构函数,那么它同样需要拷贝和赋值操作。基类的析构函数并不遵循上述准则,它是一个重要的例外。

  • 相关阅读:
    SettingsProvider 它SettingsCache
    14、Cocos2dx 3.0三,找一个小游戏开发Scene and Layer:游戏梦想
    open-flash-chart2各种效果
    Android使用surface直接显示yuv数据(三)
    LeetCode:Populating Next Right Pointers in Each Node
    zoj 3203 Light Bulb,三分之二的基本问题
    POJ 2485 Highways
    Leetcode
    android音乐柱状频谱实现
    Android自定义控件实战——水流波动效果的实现WaveView
  • 原文地址:https://www.cnblogs.com/yangguang-it/p/6534510.html
Copyright © 2020-2023  润新知