条款34:区分接口继承以及实现继承

在普通的public继承中,实际上也分为接口以及实现继承。首先看下面这个例子:

 1 class Shape{
 2 public:
 3     virtual void draw() const = 0;
 4     virtual void error(const std::string & msg);
 5     int ObjectId() const;
 6 };
 7 class Recantagle : public Shape{
 8     ...
 9 };
10 class Ellipse : public Shape{
11     ...
12 };
首先,pure virtual函数必须被继承了他们的具体class重新声明,这是典型的接口的性质,(例如java中的接口)。所以说:声明一个pure virtual函数只是为了让derived class只继承其接口。而且甚至还可以给virtual函数一个定义,只要不声明这个对象就可以了。使用的方法是加上基类的限定符,即Shape::draw();
 
再者,声明impure virtual函数的目的,是让derived class接受该函数的接口以及默认的实现。但是有时候可能会忘了实现Derived版本的相应函数,导致继承了基类版本的不希望用的实现。例如下面这个例子:
 1 class Ariport{
 2     ...
 3 };
 4 class Airplane{
 5 public:
 6     virtual void fly(const Ariport & dest);
 7     ...
 8 };
 9 class ModelA : public Airplane{
10     ...
11 };

这里可能会忘了做ModelA的相应的fly实现从而使用了可能不希望使用的基类版本,这可以通过另一种方式来解决这种问题。

 1 class Airplane{
 2 public:
 3     virtual void fly(const Airplane & dest) = 0;
 4     ...
 5 protected:
 6     void defaultFly(const Airplanes & dest);
 7 };
 8 class ModelA : public Airplane{
 9 public:
10     virtual void fly(const Airplane & dest)
11     {defaultFly(dest);}
12     ...
13 };
14 class ModelB : public Airplane{
15 public:
16     virtual void fly(const Airplane & dest)
17     {//单独为自己机型定义的fly函数}
18     ...
19 };
这样就不会忘了为特定的机型定义特定的fly函数了。上面的方法实际上通过不同的函数分别提供了接口以及缺省实现。
当然,大众的实现上面所说的方法还是实现一份纯虚函数,并且给他一份定义即可 :
 1 class Airplane{
 2 public:
 3     virtual void fly(const Airplane & dest) = 0
 4     {
 5         ....//自定义的实现
 6     }
 7     ...
 8 };
 9 class ModelA : public Airplane{
10 public:
11     virtual void fly(const Airplane & dest)
12     {Airplane::fly(dest);}
13     ...
14 };
15 class ModelB : public Airplane{
16 public:
17     virtual void fly(const Airplane & dest)
18     {//自定义的fly行为}
19     ...
20 };
这里即将用同一个函数提供了接口以及非默认的实现。这样做有一个小小的缺点就是失去可定义的一个protected函数(这是一个实现)。
而非虚函数的意义就是:使得derived拥有基类声明的一个强制性的实现。
pure virtual, virtual, 以及 none pure函数之间的差异提供两个给了我们几个选择:只继承接口,继承接口以及默认的实现,以及只集成默认实现。
 
小结:
    接口继承与实现继承之间是不同的,public继承下,derived class总是集成base class的接口
    pure virtual函数只是具体指定接口集成
    impure virtual函数具体指定接口继承以及缺省的实现继承。
    non-virtual函数具体指定了接口集成以及强制性的实现继承
原文地址:https://www.cnblogs.com/-wang-cheng/p/4889769.html