c++学习:虚析构函数+实战

发布时间:2023年12月19日

思考为什么要虚析构函数

应用类型一

基类A,派生类B,基类指针指向派生类对象,然后释放派上类对象

代码

#include <iostream>

using namespace std;

class A{
public:
    A(){cout<<__FUNCTION__<<endl;}
    virtual ~A(){cout<<__FUNCTION__<<endl;}
};



class B:public A
{
public:
    B(){
        str= new char[256];
        cout<<__FUNCTION__<<endl;
    }
     ~B(){
        delete []str;
        cout<<__FUNCTION__<<endl;
    }
private:
    char*str;
};

int main()
{
    //基类指针指向派生类对象
    A*b1 = new B;

    delete b1;

    return 0;
}

它只会调用基类析构函数,不会调用派生类析构函数,就会导致派生类里申请的字符串空间没被释放,导致内存泄漏,我们想解决这个问题,就要将基类的析构函数定义为虚函数,他就也会调用派生类的析构函数,不会导致内存泄漏

修改代码如下

class A{
public:
    A(){cout<<__FUNCTION__<<endl;}
    virtual ~A(){cout<<__FUNCTION__<<endl;}
};

应用类型二

当一个函数里面的参数是基类地址,函数作用又是释放参数所指的基类对象,传进来的又是派生类,我们该如何写代码呢,我们就可以用到虚析构函数,只要将基类的析构函数变成虚函数,无论传进来的是什么派生类,都可以安全的释放内存,不会不调用派生类的析构函数

代码

#include <iostream>

using namespace std;

class A{
public:
    A(){cout<<__FUNCTION__<<endl;}
    virtual ~A(){cout<<__FUNCTION__<<endl;}

    virtual void test();
};


void A::test()
{

}

class B:public A
{
public:
    B(){
        str= new char[256];
        cout<<__FUNCTION__<<endl;
    }
     ~B(){
        delete []str;
        cout<<__FUNCTION__<<endl;
    }
private:
    char*str;
};

class C:public A{
public:
    C(){
        str= new char[256];
        cout<<__FUNCTION__<<endl;
    }
     ~C(){
        delete []str;
        cout<<__FUNCTION__<<endl;
    }
private:
    char*str;
};

void test01(Base *p) 
{
    delete p;
}
int main()
{
    test01(new Child);
    test01(new Child1);

    return 0;
}

总结

系统在执行delete释放堆空间的时候, 只会检查这个指针本身的数据类型,所以导致 虽然b1指向的是派生类的堆空间,但是只会执行b1本身数据类型的基类的析构函数,而不会执行派生类的析构函数,导致派生类中的析构函数里面的指针成员指向的堆空间没有释放,造成内存泄漏。

C++中考虑到这种特殊情况,提供了一种解决方法: 将基类的析构函数声明为 虚析构

文章来源:https://blog.csdn.net/weixin_59669309/article/details/135074531
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。