基类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++中考虑到这种特殊情况,提供了一种解决方法: 将基类的析构函数声明为 虚析构