条款32:确定你的public继承塑模出is-a关系

来源:互联网 发布:音频频谱软件 编辑:程序博客网 时间:2024/05/16 17:11

.首先看见标题是不是有点懵,感觉很高大尚唬人的一个名字is-a,但是下面我就来解释一下什么是is-a关系,看完本篇博客后你就觉得其实原来是个“挫逼”!

1.public继承意味着is-a的关系,简单来讲is-a的关系就是:适用于基类的每一件事情一定也适用于public继承的派生类身上,因为每个派生类也都是一个基类对象。

在基类可以派上用场的任何地方,派生类一样可以派上用场,因为每个派生类对象都是一种基类对象,反之则不成立!

下面我用代码说明一下is-a的关系

class person{};class student :public person{};//因为是公有继承满足is-a的关系void eat(const person& p);//需要person(基类)的函数void study(const student& s);//需要student(派生类)的函数person p;student s;//下面开始阐述is-a的特性eat(p);//正确eat(s);//正确,s是学生,学生是人,基类可以用的地方派生类也可以study(s);//正确study(p);//错误,p不是学生,即反之不行原则//这就是典型的一种is-a的关系
虽然说is-a之间的关系听起来比较简单,但是有时候也会误导你

比如1:企鹅是鸟,鸟会飞,如果企鹅类继承鸟类,可是企鹅不会飞,与现实矛盾。

class bird{void fly(){};};class Penguin :public bird{};//按照这么继承,企鹅就会飞了,与现实中矛盾
这就需要我们自己做一定的改造了

改造方法1:

class bird{};class Flybird :public bird{virtual void fly(){};};//会飞的鸟让他飞class Penguin :public bird{};//按照这么继承,就解决了上面的问题
但是可能程序并不关系你会飞不会飞,你因为会不会飞而刻意设计出这种多继承,显得偏离了设计的重点没有必要,所以还是双clss继承的设计更好一定,因此有人又想出了一种双class继承体系上使其符合现实,代码如下:

void error(const std::string& msg);//报错函数class bird{void fly(){};};class Penguin :public bird{virtual void fly(){error("企鹅不会飞这是个错误");//如果试图让企鹅飞代码会在这里报错}};

上面的代码满足双class继承,他是在你试图让企鹅飞的时候产生一个错误,从而使满足企鹅不会飞这一事实符合现实,但是这里是运行期间才会产生错误。

有句话说“好的接口可以防止无效的代码编译通过"但是上面的设计貌似不符合这个,他会产生没有用的报错代码,所以我们应该让编译器在编译器间就拒绝企鹅会飞这个问题,而不是在运行期间才拒绝,所以就有了下面的这种改造,

class bird{};class Penguin :public bird{};
这样只要你试图让企鹅飞他就会在编译期间出错。

上面的例子只是想说明,is-a的关系一定要慎重考虑设计,不要被误导。

阅读全文
0 0
原创粉丝点击