1 简要介绍
以”What”,”When”,”Why”和”How”分别介绍纯虚函数。
为什么需要纯虚函数?
当基类的接口难以描述和实现时,需要使用虚函数。例如基类形状,派生类正方形和圆。那么派生类由于是具体的形状,因此可以定义接口Draw( ),而且非常好实现,内容就是分别描述方形和圆形的画法。但是对于基类形状而言,由于不是具体的所以根本没法实现Draw()接口。
此时可能会有一种解决方案,即形状没有Draw接口,它是派生类独有的。但是这又与C++的多态违背。即不能用基类指针,如下代码无法实现。
Shape* b;
Circle* c;
Square* s;
b = (Shape*)c;
b->Draw();
【为什么不直接调用c->Draw(),因为如果这样实现就不能用一致的基类角度使用和看待派生类对象】;
因此,为了解决上述问题,就引入了纯虚函数。
什么是纯虚函数和怎么定义纯虚函数?
即指通常不需要实现的接口,事实上除了析构函数要定义成纯虚函数时需要简单实现以外,其它情况都不需要实现。
Class类名{
virtual返回值类型 函数名(参数表)= 0 ;
}
Class Shape{
Virtual void Draw(void)=0;
}
什么时候需要使用纯虚函数?
满足两个条件:1需要会用基类对象/引用/指针来一致性地访问所有派生类;2而且基类无法给出具体实现。
2 抽象类
只要定义了纯虚函数后,基类就称为抽象类。它很特别,不能定义抽象类对象,只能定义抽象类指针或者引用。
3 纯虚析构函数
从抽象类的定义可以看出,是无法定义抽象类对象的,这是一个非常有用的性质,当程序不希望任何使用者直接定义该类的对象时,即可将该类实现成抽象类。
但是考虑更为特殊的情况,如果该类没有任何接口时,而又想让它实现成抽象类的效果,此时就需要使用每个类自带的函数,析构函数(为什么不使用构造函数,因为构造函数不能被定义成虚函数,更不可能是纯虚函数。为什么不能是虚函数,因为虚函数需要通过虚表指针访问得到,而调用构造函数时对象都没有构造,根本就没有虚表指针)。
之所以将其单独抽取出来介绍,是因为它实现有另外一个特点,即需要给出实现,实现可以是空,如下所示。
Class Base{
virtual ~Base() = 0
{
}
}