[笔记]《Effective C++》第六章 Inheritance and Object-Oriented Design
条款32:Make sure public inheritance models"is-a."
“public继承”意味is-a。适用于base classes身上的每一件事情一定也适用于derived classes身上,因为每一个derived class对象也都是一个base class对象。
必须牢记:
- public inheritance(公开继承)意味 "is-a"(是一种)的关系。
条款33:Avoid hiding inherited names.
- derived classes内的名称会遮掩base classes内的名称。在public继承下从来没有人希望如此。
- 为了让被遮掩的名称再见天日,可使用using声明式或转交函数(forwarding functions)。
条款34:Differentiate between inheritance of interface and inheritance of implementation.
- public继承下,成员函数的接口总是会被继承。
- 声明一个pure virtual函数的目的是为了让derived classes只继承函数接口。
- 我们可以为pure virtual函数提供定义,调用它的唯一途径是“调用时明确指出其class名称”。
- 声明简朴的(非纯)impure virtual函数的目的,是让derived classes继承该函数的接口和缺省实现。
- 声明non-virtual函数的目的是为了令derived classes继承函数的接口及一份强制性实现。
- 一个non-virtual成员函数所表现的不变性(invariant)凌驾其特异性(specialization),所以它绝不该在derived class中被重新定义。
条款35:Consider alternatives to virtual functions.
可以采用以下方法作为虚函数的替代:
- 藉由Non-Virtual Interface手法实现Template Method模式。
- 藉由Function Pointers实现Strategy模式。
- 藉由tr1::function(C++11中已经加入标准库)完成Strategy模式。tr1::function对象的行为就像一般函数指针。这样的对象可接纳“与给定之目标签名式(target signature)兼容”的所有可调用物(callable entities)。
- 古典的Strategy模式。将继承体系内的 virtual函数替换为另一个继承体系内的virtual函数。
条款36:Never redefine an inherited non-virtual function.
任何情况下都不该重新定义一个继承而来的non-virtual函数。
条款37:Never redefine a function's inherited default parameter value.
virtual函数系动态绑定(dynamically bound),而缺省参数值却是静态绑定(statically bound)。
- 对象的所谓静态类型(static type),就是它在程序中被声明时所采用的类型。
- 对象的所谓动态类型(dynamic type)则是指“目前所指对象的类型”。
条款38:Model "has-a" or "is-implemented-in-terms-of" through composition.
- 复合意味has-a(有一个)或is-implemented-in-terms-of (根据某物实现出)。
- 当复合发生于应用域内的对象之间,表现出has-a的关系;当它发生于实现域内则是表现is-implemented-in-terms-of的关系。
- 程序中的对象其实相当于你所塑造的世界中的某些事物,例如人、汽车、一张张视频画面等等。这样的对象属于应用域(application domain)部分。
- 其他对象则纯粹是实现细节上的人工制品,像是缓冲区(buffers)、互斥器(mutexes)、查找树(search trees)等等。这些对象相当于你的软件的实现域(implementation domain)。
条款39:Use private inheritance judiciously.
1 Private继承意味is-implemented-in-terms of(根据某物实现出)。它通常比复合(composition)的级别低。但是当derived class需要访问protected base class的成员,或需要重新定义继承而来的virtual函数时,这么设计是合理的。
2 和复合(composition)不同,private继承可以造成empty base最优化(EBO)。这对致力于“对象尺寸最小化”的程序库开发者而言,可能很重要。
- 如果classes之间的继承关系是private,编译器不会自动将一个derived class对象(例如Student)转换为一个base class对象(例如Person)。
- 由private base class继承而来的所有成员,在derived class中都会变成private属性,纵使它们在base class中原本是protected或public属性。
- private继承意味只有实现部分被继承,接口部分应略去。
- 尽可能使用复合,必要时才使用private继承。
条款40:Use multiple inheritance judiciously.
1 多重继承比单一继承复杂。它可能导致新的歧义性,以及对virtual继承的需要。
2 virtual继承会增加大小、速度、初始化(及赋值)复杂度等等成本。如果virtual base classes不带任何数据,将是最具实用价值的情况。
3 多重继承的确有正当用途。其中一个情节涉及“public继承某个Interface class”和“private继承某个协助实现的class”的两相组合。
对virtual base classes(亦相当于对virtual继承)的忠告:
- 第一,非必要不使用virtual bases。平常请使用non-virtual继承。
- 第二,如果你必须使用virtual base classes,尽可能避免在其中放置数据。
分类:
读书笔记
标签:
Note
, Effective C++
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!