zoukankan      html  css  js  c++  java
  • 条款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函数具体指定了接口集成以及强制性的实现继承
  • 相关阅读:
    VS 2012 + NDK + ADT 开发(Cocos2d-x 3.1开发)PART 2
    VS 2012 + NDK + ADT 开发(Cocos2d-x 3.1开发)PART 1
    WebView读取SD卡上的HTML
    安卓隐藏控件
    OMNET++安装
    产品质量的核心——概念的完整性
    关于异常
    基类与子类之间的引用转换
    成绩划分 处理异常
    《大道至简 第七、八章》读后感
  • 原文地址:https://www.cnblogs.com/-wang-cheng/p/4889769.html
Copyright © 2011-2022 走看看