文章目录
Tips1
polymorphic(带有多态性质的)base classes应该声明一个virtual的虚构函数。如果class带有任何virtual函数,它就应该拥有一个virtual析构函数。
Tips2
Classes的设计目的如果不是作为 base classes 使用,或者不是为了具备多态性(polymorphically),就不该声明virtual析构函数。
一、为什么要有virtual析构函数?
C++明确指出,当derived class对象经由一个base class指针被删除,而base class带有一个non-virtual析构函数,其结果未有定义,实际执行时通常发生的是对象的derived成分没被销毁。
class SpecialString: public std::string
{
//馊主意!std::string有个non-virtual的析构函数
}
// 错误使用方法
SpecialString *pss = new SpecialString("Bad Action");
std::string *ps;
...
ps = pss; //SpecialString* => std::string*
...
delete ps; //未有定义!
//现实中 *ps 的SpecialString资源造成了泄露,因为SpecialString的析构函数未被调用。
//虚表指针觉得这个时候应该调用std::string的析构函数。
二、为什么有时候不要声明虚构函数?
如果你不想让一个类成为基类,那么在类中声明虚函数是是一个坏主意,因为额外存储的虚表指针会使类的体积变大。考虑如下情况:
class Point
{
public:
Point(int x, int y); //一个二维空间点
~Point();
private:
int x;
int y;
}
Point对象可以塞入到一个64-bit的缓存器中。如果Point的析构函数是virtual 的话,该对象的体积变大了,因为还需要存放虚表指针vptr(virtual table point)。虚表(vtbl)的占用倒是无关紧要,因为多个Point对象共用一个vtbl。在32-bit计算机体系结构中,Point占用空间大小由64bit(2个int)变成96bit(2个int和1个vptr);在64-bit架构中可能占用64-128bits,因为此时指针占64bits。因此一个virtual虚构函数将会导致对象大小增加50%~100%!
这样Point对象也不能塞入到一个64-bit的缓存器了,C++的Point对象就不能再和其他语言(如C)的相同声明具备一样的结构了,因此也无法传递至其他语言写的函数中去了。
三、使用一下纯虚函数。
虚析构函数的运作方式是,最深层派生的那个类的析构函数最先被调用,然后是其上的基类的析构函数被依次调用。如果你想将基类作为抽象类使用,但似乎没有适合的函数作为虚函数,那么将它的析构函数设为纯虚函数是一个不错的想法。下面是个例子:
class AWOV
{
public:
virtual ~AWOV() = 0;
}
然后你必须要为纯虚函数析构提供一份定义:
AWOV::~AWOV(){}
Today Thinking~
和技术无关的瞎想
1+1=2吗?这是约定了某种规则吧。
二进制下1+1=10。
1个苹果+1个苹果=2个苹果?
如果按照重量规定,100g是一个苹果,一个重100g,另一个重150g,那么1+1=2.5?
如果我要加的是今天的这个苹果和昨天的同一个苹果,那么1+1=1?
所以结果不同是因为我们所框定的规则不同吧。