C++ 编译告警: delete called on that is abstract but has non-virtual destructor

上述告警在使用arm编译器编译的时候报出,意思是缺少虚的析构函数,在delete被调用的时候,会造成问题。典型的就是内存泄漏。看例子:、

1. 正常情况

#include <iostream>

class Base{
    public:
    Base(){
        std::cout << "Base constructor is called." << std::endl;
    }
    ~Base(){
        std::cout << "Base destructor is called." << std::endl;
    }
};

class Child:public Base{
    public:
    Child(){
        std::cout << "Child constructor is called." << std::endl;
    }
    ~Child(){
        std::cout << "Child destructor is called." << std::endl;
    }
};

上面代码中的两个类,一个是基类Base,一个是继承Base的子类Child。按照正常的声明方式,调用运行。

int main(){

    Child child_example1;
    
    return 0;
}

输出的结果如下图所示:

Base constructor is called.
Child constructor is called.
Child destructor is called.
Base destructor is called.

这是最正常的情况,声明了一个子类,首先会调用父类的构造函数,然后调用子类的构造函数。析构时先调用子类的析构函数,再调用父类的析构函数。

2. 告警情况

那么,什么时候会出现warning: delete called on that is abstract but has non-virtual destructor [-Wdelete-non-virtual-dtor]这个告警呢。就是当我们希望用父类指针指向子类的时候,即发生动态链编的情况。

int main(){
    
    Base* child_example2 = new Child();
    delete child_example2;
    child_example2=nullptr;

    return 0;
}

运行结果如下图所示:

Base constructor is called.
Child constructor is called.
Base destructor is called.

warning就是在这时候产生的,而实际的效果就是在析构的时候,只调用了基类的析构函数,而没有调用子类的析构函数。这就会造成内存泄漏。

其实用到C++的继承,那么用父类指针指向子类的情况还是非常的常见的。那如何规避上述问题呢,就是需要对父类的析构函数使用虚函数。

#include <iostream>

class Base{
    public:
    Base(){
        std::cout << "Base constructor is called." << std::endl;
    }
    virtual ~Base(){ // 父类的析构函数使用虚函数
        std::cout << "Base destructor is called." << std::endl;
    }
};

class Child:public Base{
    public:
    Child(){
        std::cout << "Child constructor is called." << std::endl;
    }
    ~Child(){
        std::cout << "Child destructor is called." << std::endl;
    }
};

int main(){
    
    Base* child_example2 = new Child();
    delete child_example2;
    child_example2=nullptr;

    return 0;
}

这样在进行运行,得到的结果如下:

Base constructor is called.
Child constructor is called.
Child destructor is called.
Base destructor is called.

就和1中的正常情况一致了。

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值