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


         




  • 相关阅读:
    【流量劫持】SSLStrip 终极版 —— location 瞒天过海
    【流量劫持】沉默中的狂怒 —— Cookie 大喷发
    【流量劫持】SSLStrip 的未来 —— HTTPS 前端劫持
    Web 前端攻防(2014版)
    流量劫持 —— 浮层登录框的隐患
    流量劫持能有多大危害?
    流量劫持是如何产生的?
    XSS 前端防火墙 —— 整装待发
    XSS 前端防火墙 —— 天衣无缝的防护
    XSS 前端防火墙 —— 无懈可击的钩子
  • 原文地址:https://www.cnblogs.com/silyvin/p/9106896.html
Copyright © 2011-2022 走看看