?纪录时间的方法很多,合理的做法是创建一个基类,并为不同的计时方法创建派生类:
class TimeKeeper {
public:
TimeKeeper();
~TimeKeeper();
...
};
class AtomicClock : public TimeKeeper { ... };
class WaterClock : public TimeKeeper { ... };
class WristWatch : public TimeKeeper { ... };
TimeKeeper* getTimeKeeper(); // 返回一个指针,指向一个动态分配的派生类对象
//…
TimeKeeper* ptk = getTimeKeeper(); // 获取动态分配的对象
... // 使用它
delete ptk; // 释放它以避免资源泄漏
我们可以看到派生类的析构函数没有执行。
class TimeKeeper {
public:
TimeKeeper();
virtual ~TimeKeeper();
...
};
TimeKeeper* ptk = getTimeKeeper();
...
delete ptk; // 现在行为正确了
?既然将析构函数声明为虚函数可以避免派生类析构函数不执行的问题,那么我们是不是把所有类的析构函数都声明为虚函数就行了呢?答案是不行。当一个类不打算成为基类时,将析构函数设为虚函数通常不是一个好主意。
class Point { // 一个2D的点
public:
Point(int xCoord, int yCoord);
~Point();
private:
int x, y;
};
主要原因如下:
使用虚函数需要而外的,名为vptr(virtual table pointer)的指针,vptr指向一个函数指针数组,称为vtbl (virtual table)。这让这个类的大小凭空多了四个字节的大小。
?标准的string类型不包含虚函数,但有时候我们会写个类继承他。
class SpecialString : public std::string { // 坏主意!string有非虚析构函数};
SpecialString* pss = new SpecialString("Impending Doom");
std::string* ps;
...
ps = pss; // SpecialString* ? std::string*
...
delete ps; // 未定义的! 实际上派生类部分会被泄露,不会调用SpecialString析构函数
有时你想创造一个抽象类,但却没有任何纯虚函数。怎么办?
解决方案很简单:在想要抽象的类中声明一个纯虚析构函数。
class AWOV { // AWOV = "Abstract w/o Virtuals"
public:
virtual ~AWOV() = 0; // 声明纯虚析构函数
};
AWOV::~AWOV() {} // 必须提供纯虚析构函数的定义