类成员析构、虚析构函数、动态生成对象相关的 关于析构顺序的杂谈

#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


     




posted on 2013-05-01 08:51  silyvin  阅读(138)  评论(0编辑  收藏  举报