结论是:
1.对象的析构会调用自己及其所有父类的析构函数(不管是否有virtual)
2.对于有virtual的析构,总是从new的类型开始,依次析构到最顶父类
3.对于无virtual的析构,总是以delete时的类类型开始,依次析构到最顶父类
下面是例子程序:
#include <iostream>
class Base
{
public:
Base()
{
std::cout<<__FUNCTION__<<std::endl;
}
virtual ~Base()
{
std::cout<<__FUNCTION__<<std::endl;
}
};
class Sub:public Base
{
public:
Sub()
{
std::cout<<__FUNCTION__<<std::endl;
}
virtual ~Sub()
{
std::cout<<__FUNCTION__<<std::endl;
}
};
class SubSub : public Sub
{
public:
SubSub()
{
std::cout<<__FUNCTION__<<std::endl;
}
virtual ~SubSub()
{
std::cout<<__FUNCTION__<<std::endl;
}
};
class Base2
{
public:
Base2()
{
std::cout<<__FUNCTION__<<std::endl;
}
~Base2()
{
std::cout<<__FUNCTION__<<std::endl;
}
};
class Sub2:public Base2
{
public:
Sub2()
{
std::cout<<__FUNCTION__<<std::endl;
}
~Sub2()
{
std::cout<<__FUNCTION__<<std::endl;
}
};
class SubSub2 : public Sub2
{
public:
SubSub2()
{
std::cout<<__FUNCTION__<<std::endl;
}
~SubSub2()
{
std::cout<<__FUNCTION__<<std::endl;
}
};
/// 结论:
/// 不管父类析构函数是否有virtual,子类析构都会调用父类的析构函数。
/// 没有virtual的父类容易造成子类的内存泄露
///
/// 对于无virtual的情况:可能存在子类的析构函数不能正确调用
/// 1.只有用父类指针去delete才不会调用子类析构函数:
/// Base2* base_sub_ptr = new Sub2();
/// delete base_sub_ptr;// 只调用父类的析构函数
///
/// Sub2* sub_sub_ptr = new Sub2();
/// delete ((Base2*)sub_sub_ptr);// 只调用父类析构
///
/// Sub2* sub_sub_ptr = new Sub2();
/// delete sub_sub_ptr;// 会调用子类父类的析构,不管是否有virtual
///
/// 也就是如果析构函数没有virtual,那么指针转换之后就可以导致不能正确析构
int main()
{
// 父类有virtual的情况
{
std::cout<<"\nBase* base_sub_ptr = new Sub();"<<std::endl;
Base* base_sub_ptr = new Sub();
delete base_sub_ptr; // 有virtual,会调用子类和父类的析构函数
}
{
std::cout<<"\nSub* base_sub_ptr = new Sub();"<<std::endl;
Sub* sub_sub_ptr = new Sub();
delete sub_sub_ptr; // 有virtual,会调用子类和父类的析构函数
}
{
std::cout<<"\nSub* base_sub_ptr = new Sub();"<<std::endl;
Base* base_base_ptr = new Base();
delete base_base_ptr; // 有virtual,调用父类析构函数
}
{
std::cout<<"\nSub* sub_subsub_ptr = new SubSub();"<<std::endl;
Sub* sub_subsub_ptr = new SubSub();
delete sub_subsub_ptr; // 有virtual,从最子类依次析构到父类
}
{
std::cout<<"\nSub* sub_subsub_ptr = new SubSub();"<<std::endl;
Base* sub_subsub_ptr = new SubSub();
delete (Sub*)sub_subsub_ptr; // 有virtual,从最子类依次析构到父类
}
{
std::cout<<"\nSub* sub_subsub_ptr = new SubSub();"<<std::endl;
Base* sub_subsub_ptr = new SubSub();
delete (SubSub2*)sub_subsub_ptr; // 有virtual,从最子类依次析构到父类
}
{
std::cout<<"\nSub* sub_subsub_ptr = new Sub();"<<std::endl;
Base* sub_sub_ptr = new Sub();
delete (SubSub2*)sub_sub_ptr; // 有virtual,从最子类依次析构到父类
}
// 父类没有virtual的情况
{
std::cout<<"\nBase2 base_base = Base2();"<<std::endl;
Base2 base_base = Base2();// 无virtual,调用父类析构函数
}
{
std::cout<<"\nSub2 sub_sub = Sub2();"<<std::endl;
Sub2 sub_sub = Sub2();// 无virtual,会调用子类和父类的析构函数
}
{
std::cout<<"\nSub2* sub_sub_ptr = new Sub2();"<<std::endl;
Sub2* sub_sub_ptr = new Sub2();
delete sub_sub_ptr;// 会调用自己及父类的析构,不管是否有virtual
}
{
std::cout<<"\nSub2* sub_sub_ptr = new Sub2();"<<std::endl;
Sub2* sub_sub_ptr = new Sub2();
delete ((Base2*)sub_sub_ptr);// 只调用Base2析构
}
{
std::cout<<"\nBase2* base_sub_ptr = new Sub2();"<<std::endl;
Base2* base_sub_ptr = new Sub2();
delete base_sub_ptr;// 只调用Base2的析构函数
}
{
std::cout<<"\nSubSub2* sub_subsub_ptr = new SubSub2();"<<std::endl;
SubSub2* sub_subsub_ptr = new SubSub2();
delete ((Base2*)sub_subsub_ptr);// 只调用Base2析构
}
{
std::cout<<"\nBase2* base_subsub_ptr = new Sub2();"<<std::endl;
Base2* base_subsub_ptr = new SubSub2();
delete (Sub2*)base_subsub_ptr;// 只调用Base2,Sub2的析构函数
}
{
std::cout<<"\nBase2* base_subsub_ptr = new SubSub2();"<<std::endl;
Base2* base_subsub_ptr = new SubSub2();
delete base_subsub_ptr;// 只调用Base2的析构函数
}
{
std::cout<<"\nBase2* base_base_ptr = new Base2();"<<std::endl;
Base2* base_base_ptr = new Base2();
delete (SubSub2*)base_base_ptr;// 调用SubSub2直到父类的析构函数
}
Sub2 sub;
{
std::cout<<"\nBase2 base_sub = Sub2();"<<std::endl;
Base2 base_sub = sub;
}
{
std::cout<<"\nBase2 base_sub = Sub2();"<<std::endl;
Base2 base_sub = Sub2();
}
std::cout<<"Test Over!"<<std::endl;
return 0;
}