《Effective C++》知识点(6)--继承与面向对象设计

本文讨论了C++中几种关键的继承模式,包括public继承的is-a原则,避免遮盖继承名称,接口与实现继承的区别,虚函数的替代方案,以及private和多重继承的合理使用。强调了明智地设计和管理继承关系的重要性。
摘要由CSDN通过智能技术生成
32. 确定你的public继承模式是is-a关系

      重要规则:public继承就意味is-a的关系。适用于基类身上的每一件事情一定也适用于继承类身

      上,因为每一个继承类对象也都是一个基类对象。

      另外两种关系是has-a(有一个)和is-implemented-in-terms-of(根据某物实现出)。

33. 避免遮盖继承而来的名称

     33.1 编译器查找函数顺序:首先查找local作用域,没找到->查找外围作用域(继承类覆盖的),

             没找到->查找基类作用域,没找到->查找包含基类的namespace作用域,没找到->最后到

             global作用域找。

     33.2 继承类内的函数名称会遮盖基类内的函数名称。在public继承下违反了is-a的原则。

     33.3 为了让被遮盖的函数可见,可使用using声明式或转交函数(继承类函数里调用基类函数)。

34. 区分接口继承和实现继承

      接口继承和实现继承不同。在public继承下,继承类总是继承基类的接口。

接口继承实现继承
纯虚函数
非纯(impure)虚函数缺省实现(允许子类有不同行为)
非虚函数强制(不允许子类有不同行为)
35. 考虑虚函数以外的其它选择

      虚函数的替代方案:

方法设计模式优点缺点说明
non-virtual interface(NVI) 手法Template Method非虚函数包装了虚函数,可以在虚函数调用前及调用之后做一些工作对public的虚函数不适合通过public非虚成员函数调用private或protected虚函数
函数指针成员变量替换虚函数Strategy模式的分解表现

1.每个对象可各自拥有自己的计算函数

2.可在运行期改变使用哪个计算函数

需要弱化class的封装性,以便非成员函数访问类的非public成员函数指针指向非成员函数,这些函数有相同的参数和返回值。
tr1::function成员变量替换虚函数Strategy模式的某种形式比函数指针更加灵活function可以是函数指针、函数对象、或成员函数指针
将继承体系内的虚函数替换为另一继承体系内的虚函数Strategy模式的传统实现增加新的计算策略类很方便策略与对象分离
36. 绝不重新定义继承而来的non-virtual函数

       任何情况下继承类都不该重新定义一个继承而来的基类non-virtual函数。如果需要重新定义,

       那说明这个函数其实应该是virtual函数。

37. 绝不重新定义继承而来的缺省参数值

     37.1 可以重定义继承而来的带有缺省参数值的virtual函数实现,但不能重定义它的缺省参数

               值。因为virtual函数是动态绑定,而缺省参数值却是静态绑定。

     37.2 为什么缺省参数值是静态绑定?

               为了运行效率。如果缺省参数值是动态绑定,编译器就必须有某种办法在运行期为虚函

               数决定适当的参数缺省值。这比目前实行的"在编译期决定"的机制更慢而且更复杂。为了

               程序的执行速度和编译器实现上的简易度,C++做了这样的去舍。

     37.3 当你想令virtual函数表现出你所想要的行为但却遇到麻烦时,考虑条款35的替代设计。 

38. 通过复合实现has-a或"根据某物实现出"

     38.1 复合(composition)的意义和public继承完全不同。

     38.2 程序中的对象相当于现实世界的某些事物,这样的对象属于应用域。其它对象如缓冲区、

             互斥器、查找树等等,属于实现域。

             当复合发生于应用域内的对象之间,表现出has-a的关系;而当它发生于实现域内则是表现

             出is-implemented-in-terms-of的关系。

39. 明智而审慎地使用private继承

     39.1 private继承的两个规则:

            a. 编译器不会自动将一个继承类对象转换为基类对象。

            b. 继承来的所有成员,在继承类中都会变成private属性。

     39.2 private继承意味is-implemented-in-terms-of,只有实现部分被继承。它通常比复合

             (composition)的级别低。尽可能使用复合,必要时使用private继承。private继承主要用

             于"想访问基类的protected成分"或为了重新定义继承而来的虚函数。

     39.3 EBO(empty base optimization)空白基类最优化

             和复合不同,private继承可以EBO(一般只在单一继承)。这对致力于"对象尺寸最小化"的程

             序库开发者而言,可能很重要(在意空间的时候)。

     39.4 空的类Empty并非不占空间,在大多数编译器中sizeof(Empty)为1。

40. 明智而审慎地使用多重继承

    40.1 多重继承比单一继承复杂。它可能导致新的歧义性(多个基类有同名接口时),以及对virtual

            继承的需要(否则钻石型多重继承时会重复复制基类成员变量)。

    40.2 虚继承会增加大小、速度、初始化(及赋值)复杂度等等成本。如果虚基类不带任何数据,将

           是最具实用价值的情况。

    40.3 两个建议:

             a. 非必要不使用virtual bases。尽量使用非虚继承。

             b. 如果必须使用虚继承,尽可能避免在其中放置数据。   

    40.4 多重继承的用途之一:

            "public继承某个接口类"和"私有继承某个协助实现的类"的组合(类适配器)。
     

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值