C++之确定你的public继承塑模出is-a关系(32)---《Effective C++》

1 篇文章 0 订阅
1 篇文章 0 订阅

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

public继承和is-a之间的等价关系听起来颇为简单,但有时候你的直觉可能会误导你,例如企鹅是一种鸟,这是一个既定事实,但是企鹅可以飞吗?

class Bird{
public:
    virtual void fly();
    ...
};
class Penguin:public Bird{
    ...
};

这下就入坑了吧!整个继承体系来说企鹅可以非,但我们知道这种绝伦是错的,那是什么情况???
这个例子中,我们就对public继承没有进行深刻了解导致被坑,我们应该承认一点:有数种鸟儿不会飞,所以public继承有问题吧!“is-a”关系并不满足!

可以为其声明一个可以使其满足“is-a”关系的基类,然后使用public继承;

class Bird{
    ...
};
class FlyingBird:public Bird{
public:
    virtual void fly();
    ...
};
class Penguin:public Bird{
    ...
};

这个例子中我们将鸟儿分为会飞的鸟儿和不会飞的鸟儿,其中penguin属于不会飞的鸟儿!!!这种关系可以得到正确的表示了吧!

也可以为且重新定义fly函数,令其产生一个运行期错误:

void error(const std::string& msg);//定义于另外某处
class Penguin:public Bird{
public:
    virtual void fly(){error("Attempt to make a penguin fly!");}
    ...
};

利用运行期错误可以解决掉这种“is-a”关系不匹配问题!

如果上面的例子理解的不是很深刻的话,那么我们提出另外一个例子,帮助理解“public继承其实是is-a关系”的这个概念:

class Rectangle{
public:
    virtual void setHeight(int newHeight);
    virtual void setWidth(int newWidth);
    virtual int height() const;
    virtual int width() const;
    ...
};
void makeBigger(Rectangle& r)
{
    int oldHeight=r.height();
    r.setWidht(r.widht()+10);
    assert(r.height()==oldHeight);//判断r的高度值是否未曾改变
}
class Square:public Rectangle{...};
Square s;
...
assert(s.width()==s.height());
makeBigger(s);
assert(s.width()==s.height());

结果很明显,对于Square来说,makeBigger之后,assert判断值应该仍旧为True,这下我们遇到一些问题:

  • 在调用makeBigger之前,s的高度和宽度相同;
  • 在makeBigger之后,s的宽度改变,但是高度不变;
  • makeBigger返回之后,s的高度和宽度人就相同,注意s事宜by
    reference方式传递给makeBigger,所以makeBigger修改的是s吱声,不是s的副本。
    这下是不是有些小尴尬呀!哈哈,注意理解public继承实际是“is-a”关系的一种表述对于继承概念的理解将有很大的提升!
    is-a并非是唯一存在与classes之间的关系,has-a和is-implemented-in-terms-of(根据某物实现出),这些关系将在后面的博客中陆续进行更新,本文只需要对public继承的is-a特性进行理解即可!

总结:
“public继承”意味着is-a,适用于base classes身上的每一件事情一定也适用于derived classes身上,因为每一个derived class对象也是一个base class对象!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值