C++明确指出:当derived class对象经由一个base class指针被删除,而该base class带着一个non-virtual析构函数,其结果未定义——实际执行时通常发生的是对象的derived成分没被销毁,而base成分会被销毁,于是造成一个诡异的“局部销毁”对象,从而导致资源泄漏,比如:
class base{
public:
base(){printf("base con\n");}
~base(){printf("base der\n");
...
};
class derived : public base{
public:
derived() {printf("derived con\n");}
~derived(){printf("derived der\n");}
...
};
int main()
{
base *b = new derived;
delete b;
return 0;
}
输出结果是:
base con
derived con
base der
解决这个问题方法很简单:给base class一个virtual析构函数即可,比如:
class base{
public:
base(){printf("base con\n");}
virtual ~base(){printf("base der\n");
...
};
class derived : public base{
public:
derived() {printf("derived con\n");}
~derived(){printf("derived der\n");}
...
};
int main()
{
base *b = new derived;
delete b;
return 0;
}
输出结果是:
base con
derived con
derived der
base der
任何class只要带有virtual函数都几乎确定应该也有一个virtual析构函数,如果class不含有virtual函数,通常表示其并不意图被用作一个base class,此时,如果令其析构函数为virtual往往是一个馊主意,比如:
class Point{ //一个二维空间点
public:
Point()(int x, int y);
~Point();
private:
int x;
int y;
};
如果int占用32 bits,那么Point对象可塞入一个64 bits缓存器中,更有甚者,这个Point对象可被当做一个”64 bits量“传给C语言撰写的函数,然而当Point的析构函数是virtual时,对象体积发生变化,增加了32 bits的vptr,大小增至96 bits,而C语言中没有vptr,因此,也就无法传递了,除非明确补偿vptr,这样也就不再具有可移植性了。
polymorphic(带多态性质的)base classes应该声明一个virtual析构函数。如果class带有任何virtua函数,它就应该拥有一个virtual析构函数。
classes的设计目的如果不作为base classes使用,或不是为了具备多态性(polymorphically),就不该声明virtual析构函数。
阅读(3494) | 评论(1) | 转发(1) |