在前面的文章中,我们引入了虚函数。所谓虚函数,就是在声明函数成员时,在函数名的前面前面加上一个virtual。
纯虚函数和抽象类现在考虑这样一种情况,假设要做一个“各个国家的人”的调查,那么这些人都会有一些统一的行为,比如:饮食、穿衣、开车......
那么就可以创建一个基类Human,然后从这个基类派生出Englishman,Chinese等类。
由于不存在没有国家的人,所以实际上不会使用Human类来定义一个人。
那么,就不需要在Human类中定义eating,wearing,driving函数,反正派生类Englishman,Chinese类中肯定会有相关的函数定义。
将Human类中的eating,wearing,driving函数,定义为纯虚函数。
当一个成员函数,被定义为virtual,同时又=0,那么这个成员函数就是纯虚函数。
含有纯虚函数的类,就是抽象类。
抽象类是为了给它的派生类定义框架,或者称为给使用这些类的应用程序定义好接口。
需要注意的是,抽象类不能用来实例化对象。
在main函数中创建一个Human类对象,然后编译。
可以看到有报错,原因为不能创建抽象类对象,即抽象类不能用来实例化对象。
修改Human的派生类Englishman和Chinese,在派生类中实现具体的eating,wearing,driving函数。
在main函数中创建两个派生类的对象,由于派生类已经覆写了所有基类的纯虚函数,所以此时编译可以成功。
如果在派生类中,缺少基类的纯虚函数的定义,那么还可以编译成功吗?
将 Chinese 中的 driving 函数定义删除,再次编译。
此时会报和之前创建 Human 类对象相同的调试信息。
这是因为,由于在派生类中没有定义 driving 函数,那么 driving 函数就还是一个纯虚函数,这个派生类也就还是抽象类,而抽象类不能实例化对象。
可以定义一个Chinese类的派生类Guangximan,在Guangximan类中定义driving函数。
此时可以创建Guangximan类的对象。
此时编译可以成功。
总结纯虚函数:
- virtual 函数声明时,后面加上 “=0”,例如virtual void eating(void) = 0;
- 纯虚函数不需要定义,只需声明;
抽象类:含有纯虚函数的类。
- 抽象类不能实例化对象;
- 若子类没有覆写完所有的纯虚函数,则子类还是抽象类;
抽象类的作用:向下定义好框架,向上提供统一的接口。