zoukankan      html  css  js  c++  java
  • 接口类

    ---------------siwuxie095

       

       

       

       

       

       

       

       

    接口类

       

       

    如果在抽象类中,仅含有纯虚函数,而不含其它任何东西,

    就称其为 接口类

       

       

       

       

    在类中,没有任何数据成员,仅有成员函数,且成员函数

    都是纯虚函数

       

       

       

    看如下实例:

       

    定义一个形状类:Shape,它是一个接口类,只有纯虚函数,

    没有数据成员

       

       

       

       

    在实际使用中,接口类更多的是用来表达一种能力 或 协议

       

       

       

       

    看如下实例:

       

    定义一个 Flyable 类,即 会飞的,如果要具有飞这种能力,

    就应该实现 takeoff() 和 land() 两个函数

       

       

       

       

    定义一个 Bird 类,并继承 Flyable 类,如果要实例化 Bird,就必须要

    实现 takeoff() 和 land() 这两个函数

       

       

       

       

    在使用时:

       

       

       

    如果有这样一个函数,它要求传入的指针是 能飞的,即 任何

    能飞的对象指针都可以传入进来,Bird 实现了 Flyable,那么

    Bird 就是一个 Flyable

       

    当子类继承父类时,就形成了一种 is-a 的关系,即 可以在

    flyMatch() 中传入两个指针,要求传入的类只要是 Flyable

    的子类即可,而 Bird 正是 Flyable 的子类,于是就可以传入

    Bird 的对象指针,传入进来的对象指针就可以调用 takeoff()

    和 land() 两个函数了

       

    Flyable 相当于一种协议,你如果想要参加飞行比赛 flyMatch(),

    必须会飞,如果会飞,那么你一定实现了takeoff() 和 land(),

    后就可以在飞行比赛 flyMatch() 中去调用了

       

       

       

    同理:定义一个 CanShot 类,即 一种射击的能力,其中有

    两个纯虚函数,一个是 aim(),一个是 reload()

       

       

       

       

    此时,再定义一个飞机类:Plane,它可以进行多继承,

    即 继承了 Flyable 和 CanShot

       

       

       

    如果 Plane 类想要实例化,就必须实现 Flyable 类中的 takeoff()

    和 land(),以及 CanShot 类中的 aim() 和 reload()

       

       

       

    如果上述内容都实现了,假设有这样一个函数:fight(),即 战斗,

    要求只需要具有能够射击的能力即可

       

       

       

    作为 Plane 来说,它既是 Flyable 的子类,也是 CanShot 的子类

       

    fight() 只要求是 CanShot 的子类即可,如果传入 Plane 的对象指针,

    是满足其参数要求的

       

    传入进来的对象指针必定是 CanShot 的子类,且一定实现了

    aim() 和 reload() 这两个函数,实现后就可以在 fight() 中调用,

    而且不用担心所传入的对象没有 aim() reload() 这两个函数

       

       

       

    对于接口类来说,更为复杂的例子是这样:

       

    当定义一个飞机类:Plane

       

       

       

    作为 Plane 来说,它一定是能飞的,所以继承 Flyable,如果想要

    实例化 Plane,就必须要实现 takeoff() 和 land() 这两个函数

       

       

       

    而战斗机 FighterJet 可以继承 Plane ,同时,战斗机还具有

    射击的能力,即 继承 CanShot

       

       

       

    注意:它的第一个父类 Plane 并不是一个接口类,而第二个父类

    CanShot 则是一个接口类

       

       

    这种情况下,从逻辑上可以理解为:

       

    战斗机 FighterJet 继承了飞机 Plane 的绝大部分属性,同时还

    具有射击的能力 CanShot,就需要在战斗机 FighterJet 中去实

    现 CanShot 中的 aim() 和 reload()

       

       

       

    实现完成后,如果有一个函数是空战:airBattle()

       

       

       

    空战时需要传入两个战斗机 FighterJet 的对象指针,因为传入的是

    战斗机 FighterJet 的对象指针,所以,战斗机 FighterJet 中一定实

    现了射击 CanShot 的两个函数,同时也肯定实现了 Flyable 中的两

    个函数,于是可以在空战 airBattle() 中放心的调用 Flyable 中所约定

    的函数,以及 CanShot 中所约定的函数

       

       

       

       

       

       

    程序:

       

    Flyable.h:

       

    #ifndef FLYABLE_H

    #define FLYABLE_H

       

    #include <iostream>

    using namespace std;

       

    //Flyable 是接口类,其中全部是纯虚函数,

    //它根本就没有实现的代码,所以不需要有 .cpp 文件

    class Flyable

    {

    public:

    virtual void takeoff() = 0;

    virtual void land() = 0;

    };

       

    //仅含有纯虚函数的类称为接口类无数据成员只有成员函数

    //在仅有的成员函数中又都是纯虚函数

    //

    //实际使用中,接口类更多的表达的是一种能力或协议

    #endif

       

       

       

    Plane.h:

       

    #ifndef PLANE_H

    #define PLANE_H

       

    #include "Flyable.h"

    #include <string>

    using namespace std;

       

       

    class Plane :public Flyable

    {

    public:

    Plane(string code);

       

    virtual void takeoff();//这里将两个纯虚函数实现

    virtual void land();

       

    void printCode();

    private:

    string m_strCode;

    };

       

    #endif

       

       

       

    Plane.cpp:

       

    #include "Plane.h"

       

    Plane::Plane(string code)

    {

    m_strCode = code;

    }

       

    void Plane::takeoff()

    {

    cout << "Plane--takeoff" << endl;

    }

       

    void Plane::land()

    {

    cout << "Plane--land" << endl;

    }

       

    void Plane::printCode()

    {

    cout << m_strCode << endl;

    }

       

       

       

    FighterPlane.h:

       

    #ifndef FIGHTERPLANE_H

    #define FIGHTERPLANE_H

       

    #include "Plane.h"

       

    class FighterPlane :public Plane

    {

    public:

    FighterPlane(string code);

    //Plane 中已经实现了 takeoff() land()

    //所以 FighterPlane 可以实现这两个函数,也可以不实现

    //如果不实现,就继承了 Plane 中的这两个函数

    virtual void takeoff();

    virtual void land();

    };

       

    #endif

       

       

       

    FighterPlane.cpp:

       

    #include "FighterPlane.h"

       

    FighterPlane::FighterPlane(string code) :Plane(code)

    {

       

    }

       

    void FighterPlane::takeoff()

    {

    cout << "FighterPlane--takeoff" << endl;

    }

       

    void FighterPlane::land()

    {

    cout << "FighterPlane--land" << endl;

    }

       

       

       

    main.cpp:

       

    #include <stdlib.h>

    #include "FighterPlane.h"

       

    void flyMatch(Flyable *f1, Flyable *f2);

       

    int main(void)

    {

    Plane p1("p-001");

    Plane p2("p-002");

    p1.printCode();

    p2.printCode();

    flyMatch(&p1, &p2);

    cout << endl;

    FighterPlane f1("f-001");

    FighterPlane f2("f-002");

    f1.printCode();

    f2.printCode();

    flyMatch(&f1, &f2);

       

       

    system("pause");

    return 0;

    }

       

    //is-a 的关系这里Flyable 就表示一种能力或协议

    //只有你具有起飞和降落的能力才能参加飞行比赛

    //

    //对于flyMatch()这个函数来说相当于限制了传入这个函数的参数类型

    //并且可以在函数体中放心的调用接口类当中所定义的纯虚函数

    //

    //此即为接口类的常见用法

    void flyMatch(Flyable *f1, Flyable *f2)

    {

    f1->takeoff();

    f1->land();

    f2->takeoff();

    f2->land();

    }

       

    //假如我们做这样的修改:(将多重继承改为多继承)

    //Plane类不再继承自FlyablePlane类中删掉两个纯虚函数及其实现

    //同时在FighterPlane类中加一个公有继承 Plane

    //FighterPlane类的其余不变

    //这样FighterPlane 就继承了一个接口类和一个普通类

    //

    //此时的全局函数flyMatch()就不能在传入Plane类的对象

    //如果将全局函数改为:

    //void flyMatch(Plane *p1,Plane *p2){ p1->printCode(); p2->printCode(); }

    //传入就是Plane类的对象

       

       

    运行一览:

       

       

       

       

       

       

       

       

       

       

    【made by siwuxie095】

  • 相关阅读:
    SimpleDateFormatter Java中的用法
    线性判别分析浅析及推导
    主成分分析(PCA)原理及推导
    浅说机器学习理论
    给“过拟合”下一个准确且规范的定义
    信息熵和Gini指数的关系
    WinRAR默认压缩格式ZIP
    批量学习和在线学习的区别
    LDA线性判别分析
    主成分分析(PCA)原理与实现
  • 原文地址:https://www.cnblogs.com/siwuxie095/p/6810731.html
Copyright © 2011-2022 走看看