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


         




  • 相关阅读:
    算法:二分图最大独立集
    算法:桶排序
    算法:二分图最小点覆盖——Konig定理
    jQuery基础整理之思维导图
    vue基础知识整理
    HTML总结
    JAVAScript总结
    栈和队列
    今日学习遇到的问题(2018.9.23)
    看了vue文档之后。。。。
  • 原文地址:https://www.cnblogs.com/silyvin/p/9106896.html
Copyright © 2011-2022 走看看