C++析构函数

来源:互联网 发布:mate10使用感受知乎 编辑:程序博客网 时间:2024/06/12 19:47
结论是:
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;}


0 0