一、作用:
定义纯虚函数是为了实现一个接口,起到一个规范的作用,规范继承这个类的程序员必须实现这个函数。
应该在什么情况下使用纯虚函数?
1、当想在基类中抽象出一个方法,且该基类只做能被继承,而不能被实例化;
2、这个方法必须在派生类(derived class)中被实现。
二、实现方式:
纯虚函数的声明,是在虚函数声明的结尾加 = 0
,没有函数体。在派生类没有重新定义虚函数之前是不能调用的。
举个例子,我们先定义一个形状类(Cshape),但凡是形状我们都要求其能显示自己。所以这个类定义如下:
class CShape
{
virtual void Show() {};
};
但没有 CShape 这种形状,因此我们不想让 CShape 这个类被实例化,我们首先想到的是将 Show 函数的定义(实现)部分删除:
class CShape
{
virtual void Show();
};
当我们使用下面的语句实例化一个 CShape 时:
CShape cs; // 这是我们不允许的,但仅用上面的代码是可以通过编译(但 link 时失败)
怎么样避免一个 CShape 被实例化,且在编译时就能被发现?
答案是:使用虚函数。
我们再次修改CShape类如下:
class CShape
{
public:
virtual void Show() = 0;
};
这时在实例化 CShape 时就会有以下报错信息:
error C2259: 'CShape' : cannot instantiate abstract class due to following members:
warning C4259: 'void __thiscall CShape::Show(void)' : pure virtual function was not defined
我们再来看看被继承的情况。我们需要一个 CPoint2D 的类,它继承自 CShape。他必须实现基类(CShape)中的 Show() 方法。
其实使用最初的本意是让每一个派生自 CShape 的类,都要实现 Show() 方法,但时常我们可能在一个派生类中忘记实现,为了避免这种情况,虚函数发挥作用了。
我们看以下代码:
class CPoint2D:public CShape
{
public:
CPoint2D()
{
printf("CPoint2D ctor is invoked/n");
};
void Msg()
{
printf("CPoint2D.Msg() is invoked/n");
};
/*---I'm sorry to forget implement the Show()---
void Show()
{
printf("Show() from CPoint2D/n");
};
------------------------------------------------*/
};
当我们实例化 CPoint2D 时,在编译时也会出现如下的报错:
error C2259: 'CShape' : cannot instantiate abstract class due to following members:
warning C4259: 'void __thiscall CShape::Show(void)' : pure virtual function was not defined
如上,我们预防了在派生类中忘记实现基类方法。