类成员析构、虚析构函数、动态生成对象相关的 关于析构顺序的杂谈
#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