条款07:为多态基类声明一个virtual析构函数
目录
1.问题
2.如何解决
3.注意事项
1.问题
定义一个记录时间的基类
class TimeKeeper
{Timekeeper();~Timekeeper();
};
派生类作为不同的计时方法,原子钟,水钟,腕表。
class AtomicClock : public TimeKeeper {...};
class WaterClock : public TimeKeeper {...};
class WristWatch : public TimeKeeper {...};
客户使用你的代码时,只想使用时间,不关系是如何计时的。可以使用工厂模式,返回一个基类的指针。
TimeKeeper *ptk = getTimerKeeper();delete ptk;
getTimerKeeper() 返回的对象必须是在堆上开辟的空间,如果在栈上除了作用与就会销毁。
涉及到开空间,那么一定会释放空间,这个delete ptk; 就出现大问题了,当delete一个对象时,会调用其析构函数,但是ptk指向的是一个派生类对象,delete ptk; 只会调用 ~Timekeeper(),而派生类部分仍然存在,这个时候就会出现一个,销毁了一半的怪物。
2.如何解决
只需将基类的虚构函数声明为 virtual即可解决这个问题。
class TimeKeeper
{Timekeeper();virtual ~Timekeeper();
};
因为这个时候去 delete ptk; 会变成多态调用,先去调用最深层次派生的析构,依次向上到基类。
3.注意事项
virtual不是胡乱加的,如果一个类成员是 两个整形的变量,那么这个类的大小是64bit,如果你添加了一个虚函数,在类空间的起始位置会添加一个虚表指针,如果是32位的机器类的大小是96bit,如果是64位机器类的大小来到了128bit。
而且添加虚函数之后,你无法将其传递给其他,语言写的函数,因为虚表指针是C++特有的。