上述告警在使用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中的正常情况一致了。