我们来使用一个例子来区分接口继承和函数实现继承:
class Shape{ //声明一个几何图形的形状类
public:
virtual void draw() const=0; //于某个隐喻的视屏中画出当前对象
virtual void error(const std::string& msg); //准备让那些“需要报导某个错误”的成员函数调用。
int objectID() const; //返回当前对象的一个独一无二的整数识别码
...
};
class Rctangle:public Shape{ ... };
class Elips:public Shape{ ... };
可以看到Shape中的纯虚拟函数draw使它成为一个抽象类。所以客户不能够创建Shape类的实体,只能创建其派生类的实体。
纯虚拟函数有两个最突出的特性:它们必须被任何“继承了它们”的具象类重新声明,而且它们在抽象类中通常没有定义。因此:
声明一个纯虚拟函数的目的是为了让派生类只继承函数接口——192
我们可以为纯虚拟函数提供定义,但调用它的唯一途径是“调用时明确指出其class名称”:
Shape* ps = new Shape; //错误!Shape是抽象的
Shape* ps1 = new Rectangle; //ok
ps1->draw(); //调用Rectangle::draw
Shape* ps2 = new Ellipse; //ok
ps2->draw(); //调用Ellipse::draw
ps1->Shape::draw(); //调用Shape::draw
ps2->Shape::draw(); //调用Shape::draw
声明简朴的impure virtual函数的目的,是让派生类继承该函数的接口和缺省实现——193
具体内容见总结(3)和(4)
总结——199
(1)接口继承和实现继承不同。在public继承之下,派生类总是继承基类的接口
(2)纯虚拟函数只具体指定接口继承
(3)简朴的impure virtual函数具体指定接口继承及缺省实现继承。
(4)non-virtual函数具体指定接口继承以及强制性实现继承。