C语言
主页 > 软件编程 > C语言 >

C++分析如何用虚析构与纯虚析构处理内存泄漏

2022-08-24 | 佚名 | 点击:

一、问题引入

使用多态时,如果有一些子类的成员开辟在堆区,那么在父类执行完毕释放后,没有办法去释放子类的内存,这样会导致内存的泄漏。如下代码段。

如果没有堆区的数据,可以不写虚析构或纯虚析构。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

#include <iostream>

#include <string>

using namespace std;

class Animal{

  public:

    Animal(){

        cout<<"Animal-构造"<<endl;

    }

      ~Animal(){

        cout<<"Animal-析构"<<endl;

    }

    virtual void Run()=0;  //纯虚函数无需实现,只需声明

};

class Cat:public Animal{

  public:

  string *s_name;

  Cat(string name){

      s_name = new string(name);//在堆区创建内存

      cout<<"Cat-构造"<<endl;

  }

  void Run()

  {

      cout<<*s_name<<"->"<<"Cat-Run"<<endl;

  }

  ~Cat(){

      cout<<"Cat-析构"<<endl;

      if(s_name!=NULL){

          delete s_name;

          s_name=NULL;

      }

  }

};

int main()

{

    Animal *a;

    a = new Cat("Tom");

    a->Run();

    delete a;   //父类指针析构的时候,不会调用子类析构函数

    return 0;

}

运行结果:

结果可以看到都有父类和子类的构造,虽然在主函数中delete 父类,但最终只有父类的析构函数,此时子类在堆区创建的s_name并没有得到释放,导致内存泄漏。

以上的问题我们引入虚析构和纯虚析构来解决——父类指针释放子类对象时不干净的问题

二、利用虚析构解决

虚析构只需要在析构函数前加关键字 virrtual 即可,再观察结果,可以看到父类和子类的都执行了析构函数,而子类中在堆区创建的数据也被释放干净,这是最终的结果!

1

2

3

virtual ~Animal(){

     cout<<"Animal析构"<<endl;

 }

三、利用纯虚析构解决

纯虚析构格式如下,和纯虚函数有点类似,但需要有具体的声明和具体的实现。纯虚析构需要在类外实现.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

class Animal{

  public:

    Animal(){

        cout<<"Animal-构造"<<endl;

    }

    //虚析构

     /*virtual ~Animal(){

        cout<<"Animal析构"<<endl;

    }*/

    //纯虚析构

    virtual ~Animal()=0;

    virtual void Run()=0;  //纯虚函数无需实现,只需声明

};

//需要有声明,也需要有实现

Animal::~Animal(){

    cout<<"纯虚析构"<<endl;

}

结果如下,和虚析构有相同的作用

四、总结

虚析构和纯虚析构

相同点: 都可以解决父类指针释放子类对象,都需要有具体的实现

不同点: 纯虚析构属于抽象类,无法实例化对象

原文链接:https://blog.csdn.net/qq_53734051/article/details/126478376
相关文章
最新更新