接口类
---------------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: virtualvoid takeoff() = 0; virtualvoid 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);
virtualvoid takeoff();//这里将两个纯虚函数实现 virtualvoid 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 中的这两个函数 virtualvoid takeoff(); virtualvoid 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"); return0; }
//is-a 的关系这里Flyable 就表示一种能力或协议 //只有你具有起飞和降落的能力才能参加飞行比赛 // //对于flyMatch()这个函数来说相当于限制了传入这个函数的参数类型 //并且可以在函数体中放心的调用接口类当中所定义的纯虚函数 // //此即为接口类的常见用法 void flyMatch(Flyable *f1, Flyable *f2) { f1->takeoff(); f1->land(); f2->takeoff(); f2->land(); }
//假如我们做这样的修改:(将多重继承改为多继承) //Plane类不再继承自Flyable类在Plane类中删掉两个纯虚函数及其实现 //同时在FighterPlane类中加一个公有继承 Plane类 //FighterPlane类的其余不变 //这样FighterPlane 就继承了一个接口类和一个普通类 // //此时的全局函数flyMatch()就不能在传入Plane类的对象 //如果将全局函数改为: //void flyMatch(Plane *p1,Plane *p2){ p1->printCode(); p2->printCode(); } //传入就是Plane类的对象 |
运行一览:
【made by siwuxie095】