A* a=new B ,delete a;会不会产生内存泄露了,露了B-A的部分。其中B为A的子类
析构函数在下边3种情况时被调用:
1.对象生命周期结束,被销毁时;2.delete指向对象的指针时,或delete指向对象的基类类型指针,而其基类虚构函数是虚函数时;3.对象i是对象o的成员,o的析构函数被调用时,对象i的析构函数也被调用。情况1请看下边代码:
#include<iostream.h>class A{ public: A() { cout<<"constructing A"<<endl; } ~A() { cout<<"destructing A"<<endl; } private: int a;};class B: public A{ public: B() { cout<<"constructing B"<<endl; } ~B() { cout<<"destructing B"<<endl; } private: int b;};void main()
{ B b;}运行结果为:
constructing A
constructing Bdestructing Bdestructing A上述代码还说明了一件事:析构函数的调用顺序与构造函数的调用顺序相反。
情况2则正好说明了为什么基类应该把析构函数声明为虚函数,请先看下边的例子:
#include<iostream.h>
class A{ public: A() { cout<<"constructing A"<<endl; } ~A() { cout<<"destructing A"<<endl; } private: int a;};class B: public A{ public: B() { cout<<"constructing B"<<endl; } ~B() { cout<<"destructing B"<<endl; } private: int b;};void main()
{ A* a = new B; delete a;}运行结果为:
constructing A
constructing Bdestructing A若将class A中的析构函数声明为虚函数,运行结果将变成:
constructing A
constructing Bdestructing Bdestructing A由此还可以看出虚函数还是多态的基础,才c++中没有虚函数就无法实现多态。因为不声明成虚函数就不能“推迟联编”,所以不能实现多态。这点上和不同,java总是“推迟联编”的,所以也剩了这些麻烦。
扯远了,再看情况3,通过下边代码表示:
#include<iostream.h>class A{ public: A() { cout<<"constructing A"<<endl; } ~A() { cout<<"destructing A"<<endl; } private: int a;};class C
{ public: C() { cout<<"constructing C"<<endl; } ~C() { cout<<"destructing C"<<endl; } private: int c;};class B: public A
{ public: B() { cout<<"constructing B"<<endl; } ~B() { cout<<"destructing B"<<endl; } private: int b; C c;};void main()
{ B b;}运行结果为:
constructing A
constructing Cconstructing Bdestructing Bdestructing Cdestructing Ab的析构函数调用之后,又调用了b的成员c的析构函数,同时再次验证了析构函数的调用顺序与构造函数的调用顺序相反。
若将上边的代码中的main()函数内容改成
A* a = new B;
delete a; 由情况2我们知道,这将不会调用class B的析构函数不会被调用,所以class C的析构函数也不会被调用。正如我们想的,运行结果为:constructing A
constructing Cconstructing Bdestructing A俗话说温故而知新,我却不想做什么师,只是希望能够和大家分享一下对析构函数和虚析构函数的更深的认识。以上代码在VC++6.0上通过,如有疏漏或错误的认识请大家指正: