抽象基类和纯虚函数
至此,已经介绍了简单继承和较为复杂的多态继承。接下来介绍抽象基类(Abstract base class, ABC)
有些时候,继承关系并不是is-a
那样简单。例如在开发图形程序时,可能会涉及到椭圆和圆,会有Ellipse
类和Circle
类。因为所有的圆都是特殊的椭圆,所以考虑从Ellipse
类派生出Circle
类。但涉及到细节时,会有很多问题。椭圆Ellipse类包含的内容有:椭圆中心的横纵坐标(x,y)、长半轴长(a)、短半轴长(b)、方向角(angle)。方法包括:移动椭圆、求椭圆面积、旋转椭圆(Rotate)、缩短或放长长短半轴。
虽然圆是一种椭圆,但如果直接用Ellipse
类派生Circle
类是笨拙的。首先,圆只需要一个值——半径——就可以描述大小和形状,不需要长半轴长和短半轴长,也不需要方向角angle
和方法Rotate()
,因为这些东西对圆来说完全没有意义。所以与其派生,不如直接定义Circle
类更简单。但是这种解决方式也不是最好的,忽略了Circle
和Ellipse
实际上有很多共同点的事实。分别定义忽略了这一事实。
因此,还有一种解决方法:从Ellipse
和Circle
类中抽象出它们的共性,将这些特效放到一个抽象基类,Abstract base class, ABC
里头,再由ABC
派生出Ellips
e和Circle
类。这样就可以实现用基类指针数组同时管理Ellipse
类和Circle
类。C++通过纯虚函数(pure virtual function)来提供未实现的函数。
1 | class BaseEllipse |
注意Area方法。在函数原型的末尾加上=0
使虚函数成为纯虚函数。这里的Area方法没有定义。这里的概念是:包含纯虚函数的类只用作基类。当类声明中包含纯虚函数时,不能创建该类对象。
现在,可以用BaseEllipse
类派生Ellipse
类和Circle
类。使用这些类的程序能够创建Ellipse
类对象和Circle
类对象,但不能创建BaseEllipse
对象。由于Ellipse
类和Circle
类有共同的基类,所以可以用BaseEllipse
指针数组同时管理这两种对象。所以说:ABC描述的是至少使用一个纯虚函数的接口。
在处理继承的问题上,抽象基类的方法更具有系统性和规范性。可以将抽象基类设计人员能够制定“接口约定”,确保从抽象基类派生的所有组件都至少支持抽象基类所制定的功能。