zoukankan      html  css  js  c++  java
  • 类成员析构、虚析构函数、动态生成对象相关的 关于析构顺序的杂谈

    #include <iostream.h>
    
    class A
    {
    public:
    	A(){cout << "A con" << endl;}
    	~A(){cout << "A des" << endl;}
    };
    
    class D
    {
    public:
    	D(){cout << "D con" << endl;}
    	~D(){cout << "D des" << endl;}
    };
    
    class E
    {
    public:
    	E(){cout << "E con" << endl;}
    	~E(){cout << "E des" << endl;}
    };
    
    class B : public A
    {
    public:
    	D d;
    	B(){cout << "B con" << endl;}
    	~B(){cout << "B des" << endl;}
    };
    
    class C
    {
    public:
    	A *pa;
    	E e;
    	C(){
    		pa = new B();
    		cout << "C con" << endl;
    	}
    	~C(){
    		delete pa;
    		cout << "C des" << endl;
    	}
    };
    
    void main()
    {
    	C c;
    }

    输出:

    E con

    A con

    D con

    B con

    C con

    A des

    C des

    E des


    构造顺序为:

    C成员e —— C构造函数 —— A构造函数 —— B的成员d —— B构造函数

    析构顺序为:

    C析构函数 —— A析构函数 —— C成员e的析构


    可知,类实例的构造顺序为:类成员 —— 构造函数

    析构顺序为:析构函数 —— 类成员

    但是,当基类指针A *指向派生类对象B b,析构时,不仅派生类B的析构函数未被调用,连派生类B的成员d也未被析构,造成内存泄漏,未知错误

    简单的说,当基类指针指向派生类对象时,delete 基类指针并未触发派生类的析构。解决方案为,将基类A的析构函数声明为虚函数:


    #include <iostream.h>
    
    class A
    {
    public:
    	A(){cout << "A con" << endl;}
    	virtual ~A(){cout << "A des" << endl;}
    };
    
    class D
    {
    public:
    	D(){cout << "D con" << endl;}
    	~D(){cout << "D des" << endl;}
    };
    
    class E
    {
    public:
    	E(){cout << "E con" << endl;}
    	~E(){cout << "E des" << endl;}
    };
    
    class B : public A
    {
    public:
    	D d;
    	B(){cout << "B con" << endl;}
    	~B(){cout << "B des" << endl;}
    };
    
    class C
    {
    public:
    	A *pa;
    	E e;
    	C(){
    		pa = new B();
    		cout << "C con" << endl;
    	}
    	~C(){
    		delete pa;
    		cout << "C des" << endl;
    	}
    };
    
    void main()
    {
    	C c;
    }

    输出:

    E con

    A con

    D con

    B con

    C con

    B des

    D des

    A des

    C des

    E des


    可以看到,在B的析构函数调用之后,B的成员d也顺利析构


    —— 再进一步,看看多个继承层次的对象动态创建时是如何析构的


    #include <iostream.h>  
          
    class A  
    {  
    public:  
    	A(){cout << "A con" << endl;}  
    	~A(){cout << "A des" << endl;}  
    };
    
    class B : public A
    {
    public:
    	B(){cout << "B con" << endl;}
    	~B(){cout << "B des" << endl;}
    };
    
    class D
    {
    public:
    	D(){cout << "D con" << endl;}
    	~D(){cout << "D des" << endl;}
    };
    
    class C : public B
    {
    public:
    	D d;
    	C(){cout << "C con" << endl;}
    	~C(){cout << "C des" << endl;}
    };
    
    void main()
    {
    	A *pa = new C();
    	delete pa;
    }

    输出:

    A con

    B con

    C con

    D con

    A des


    只调用了A的析构函数,B、C的析构函数及对象d的析构均未发生


    #include <iostream.h>  
          
    class A  
    {  
    public:  
    	A(){cout << "A con" << endl;}  
    	virtual ~A(){cout << "A des" << endl;}  
    };
    
    class B : public A
    {
    public:
    	B(){cout << "B con" << endl;}
    	~B(){cout << "B des" << endl;}
    };
    
    class D
    {
    public:
    	D(){cout << "D con" << endl;}
    	~D(){cout << "D des" << endl;}
    };
    
    class C : public B
    {
    public:
    	D d;
    	C(){cout << "C con" << endl;}
    	~C(){cout << "C des" << endl;}
    };
    
    void main()
    {
    	A *pa = new C();
    	delete pa;
    }

    输出:

    A con

    B con

    D con

    C con

    C des

    D des

    B des

    A des


    将C的实例给B的指针

    #include <iostream.h>  
          
    class A  
    {  
    public:  
    	A(){cout << "A con" << endl;}  
    	virtual ~A(){cout << "A des" << endl;}  
    };
    
    class B : public A
    {
    public:
    	B(){cout << "B con" << endl;}
    	~B(){cout << "B des" << endl;}
    };
    
    class D
    {
    public:
    	D(){cout << "D con" << endl;}
    	~D(){cout << "D des" << endl;}
    };
    
    class C : public B
    {
    public:
    	D d;
    	C(){cout << "C con" << endl;}
    	~C(){cout << "C des" << endl;}
    };
    
    void main()
    {
    	B *pa = new C();
    	delete pa;
    }

    输出同样的结果,将A的析构函数改为非虚


    #include <iostream.h>  
          
    class A  
    {  
    public:  
    	A(){cout << "A con" << endl;}  
    	~A(){cout << "A des" << endl;}  
    };
    
    class B : public A
    {
    public:
    	B(){cout << "B con" << endl;}
    	~B(){cout << "B des" << endl;}
    };
    
    class D
    {
    public:
    	D(){cout << "D con" << endl;}
    	~D(){cout << "D des" << endl;}
    };
    
    class C : public B
    {
    public:
    	D d;
    	C(){cout << "C con" << endl;}
    	~C(){cout << "C des" << endl;}
    };
    
    void main()
    {
    	B *pa = new C();
    	delete pa;
    }
          
    

    输出:

    A con

    B con

    D con

    C con

    B des

    A des


    将B的析构函数声明为虚函数:


    #include <iostream.h>  
          
    class A  
    {  
    public:  
    	A(){cout << "A con" << endl;}  
    	~A(){cout << "A des" << endl;}  
    };
    
    class B : public A
    {
    public:
    	B(){cout << "B con" << endl;}
    	virtual ~B(){cout << "B des" << endl;}
    };
    
    class D
    {
    public:
    	D(){cout << "D con" << endl;}
    	~D(){cout << "D des" << endl;}
    };
    
    class C : public B
    {
    public:
    	D d;
    	C(){cout << "C con" << endl;}
    	~C(){cout << "C des" << endl;}
    };
    
    void main()
    {
    	B *pa = new C();
    	delete pa;
    }
          
    

    输出:

    A con

    B con

    D con

    C con

    C des

    D des

    B des

    A des


         




  • 相关阅读:
    Java辅助类持续汇总~
    Java关于数字工具类~持续汇总~
    Java关于字符串工具类~持续汇总~
    Java关于日期的计算持续汇总~
    antlr v4 使用指南连载4——词法规则入门之黄金定律
    antlr v4 使用指南连载3——g4文件概览
    antlr v4 使用指南连载2——准备环境
    antlr 4新特性总结及与antlr v3的不同
    antlr v4 使用指南连载1——简介
    Angularjs中使用$location获取url参数时,遇到的坑~~~
  • 原文地址:https://www.cnblogs.com/silyvin/p/9106896.html
Copyright © 2011-2022 走看看