多态部分,基类使用虚析构函数。
将动态申请的派生类对象指针赋给基类指针。
最后在调用delete释放基类指针指向的内存的时候,不仅会调用派生类的析构函数,也会调用基类的析构函数。
这就与普通的虚成员函数不一样,普通的虚成员函数调用只会调用派生类的成员函数,而不会调用基类的成员函数。
如下面的演示程序所示:
#include <iostream>
using namespace std;
class Base{
public:
Base(){}
virtual fun(int a){
cout<<"Base::fun(int) a= "<<a<<endl;
}
virtual ~Base() {//注:虚析构函数
cout<<"Base destructor!"<<endl;
}
};
class Derived : public Base{
public:
Derived(){}
fun(int a){
cout<<"Derived::fun(int) a= "<<a<<endl;
}
~Derived(){
cout<<"Derived destructor!"<<endl;
}
};
int main()
{
Base *p=new Derived();
p->fun(99);
delete p;
//使用虚析构函数时,既调用了基类析构函数,也调用了派生类析构函数
return 0;
}
结果:
所以,需要注意的是,派生类的虚析构函数中就不要再重复释放基类中的动态申请的成员了。
如下程序,重复释放内存引起错误:
#include <iostream>
using namespace std;
class Base {
public:
Base() {
_elem = new int;
}
virtual ~Base() {
delete _elem;
cout << "Base destructor!" << endl;
}
protected: // private会无法访问
int *_elem;
};
class Derived : public Base {
public:
Derived() :Base() {
_elem2 = new int;
}
~Derived() {
delete _elem;
delete _elem2;
cout << "Derived destructor!" << endl;
}
private:
int *_elem2;
};
int main() {
Base *p = new Derived();
delete p;
//使用虚析构函数时,既调用了基类析构函数,也调用了派生类析构函数
return 0;
}
VS2017运行结果:异常退出
然而在Dev-C 5.11中此代码段 运行未报错。
delete之后的指针是未定义的,即所谓的野指针,跟 具体编译器有关,不同编译器是不同的。
总之,不要重复释放内存。