《Effective C++》重点摘要(六)

17 篇文章 0 订阅

《Effective C++》第六章:继承与面向对象设计

  1. 确定你的public继承塑模出is-a关系。student is a person,所以student可以public继承自person。概念上,正方形是长方形,但是如果让square继承自rectangle呢,square需要像rectangle那样具有长和宽两个成员变量吗?如果是,每次改变正方形的宽的时候,也要改变正方形的长,这很奇怪不是吗?所以is-a关系不仅仅是现实概念上的,也是实现上的,确保对于base class对象身上发生的每件事对derived class对象而言是自然的,因为public意味着is-a关系。
  2. 避免遮掩继承而来的名称。public继承时,如果derived class内有与base class同名的函数,是同名,不管是否virtual、参数类型、常量性,那么derived class中的函数都会屏蔽掉base class中的那些(不是一个,而是所有)函数,原因是编译器解析函数名称时的查找规则。屏蔽base class中的函数往往不是我们想要的,因为derived class object is-a base class object。解决方案是在derived class声明中加上语句using::member_function_name;只是member_function_name没有其他。
  3. 区分接口继承和实现继承。以下几条法则针对public继承有效:
    1) 成员函数的接口总是会被继承。
    2) pure virtual函数的目的是为了继承接口。
    3) impure virtual函数的目的是为了继承接口和一份缺省实现,derived class可以改写实现。
    4) non-virtual函数——在不违反上一条的情况下——则是为了继承接口与一份不可更改的实现。
    设计合理的接口,选择需要的继承类型。
  4. 考虑virtual函数以外的其他选择。为了表现多态,除了简单的virtual函数的继承外,还可以有另外的选择,它们可以是:
    1) non-virtual interface手法实现的Template Method(这是指设计模式中的模板方法,不是C++中的模板)。这可以避免许多重复的代码,仅仅把non-virtual interface中变化的一小部分做成virtual就行了。
    2) strategy模式。C++拥有多种编程范式,所以实现strategy的方式很多。可以使用设计模式中的传统strategy方法(藉由多态),也可以利用函数指针,还可以使用functor(仿函数),还可以使用委托,嗯?C++中的委托?你可以模拟,利用模板,我前面的博文利用C++11的新特性简单模拟了一个委托http://blog.csdn.net/liao_jian/article/details/44993497,C++98嘛,那要花费很大的心力了。委托可以利用函数指针和functor,区别是委托比这两位更灵活。
  5. 绝不重新定义继承而来的non-virtual函数。好了,这和前面的内容一致了,记得函数接口的四种语义吗?再说一遍,设计合理的接口,选择需要的继承类型。
  6. 绝不要重新定义继承而来的缺省参数。遵循上一条,就让这一条涉及的面缩小了一点,virtual表示动态的(取决于运行时的实际类型),而缺省意味着静态的(编译时确定的),如果你想让一个动态的接口拥有静态的参数,当你使用多态时,在派生类中缺省参数无论你如何改写,都是来自基类的,而运行的函数则是derived版本。如果想改写缺省参数,那结果肯定不是想要的。最好考虑一下使用替代的方法改写virtual接口,如果不能,考虑一下设计是否恰当。总之不要重新定义继承而来的缺省参数,重定义没有效果。
  7. 通过复合塑模出has-a语义或”根据某物实现出“语义。A拥有B,那就使用复合,A的一些操作需要B的一些操作完成,但是B is not a A,也可以使用复合,尽量避免不要使用继承,这会为类设计带来低内聚和紧耦合的问题。复合的形式可以是A类中含有一个B类成员,也可以是A类中某个成员函数使用了B类对象作为参数。
  8. 明智而审慎地使用private继承。如果使用private继承,编译器不会为derived class转换为一个base class;从base class中继承而来的成员(函数和变量)都会变成private的。这表示继承来的东西只是一些实现层面的,不会被外部访问,所以不会涉及设计层面,而根据上一条,这种关系最好使用复合替代。如果在考虑了各种其他替代方案之后,还是需要用private继承的话,才能使用。
  9. 明智而审慎地使用多重继承。多重继承有用,但是多重继承往往比单一继承复杂,并且容易导致歧义产生概率的增高(还记得钻石型结构吗?),virtual继承是解决歧义的一种方法,但是却不得不为此付出空间、效率、初始化复杂度的代价,对于virtual base class尽量不用,如果用了,也不要再其中放置数据成员。多重继承的一个应用场景是“public继承自某个interface class”与“private继承自某个协助实现的class”的两相组合。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值