《Effective C++》继承与面向对象设计
来源:互联网 发布:php数组相同键值相加 编辑:程序博客网 时间:2024/05/18 14:12
Item 32:确定你的public继承塑膜出is-a的关系
如果你令class D以public继承class B,你便是告诉编译器说,每一个类型为D的对象同时也是一种B对象,反之如果你需要一个D对象,B对象无法效劳,因为虽然每个D对象都是一个B对象,反之不成立。
**总结:**public继承意味着is-a,适用于base classes身上的每一件事也适用于derived classes身上,因为没一个derived class都是一个base class对象。
Item 33:避免遮掩继承而来的名称
总结:①derived class内的名称会遮掩base class内的名称,在public继承下从来没有人希望如此。
②为了让被遮掩的名称在见天日,可使用using声明式或者转义函数。
Item 34:区分接口继承和实现继承
总结:①接口继承和实现继承不同,在public继承之下,derived class总是继承base class的接口。
②pure virtual函数只具体指定接口继承。
③impure virutal函数具体指定接口继承及缺省实现继承。
④non-virtual函数具体指定接口继承以及强制性实现继承。
Item 35:考虑virtual函数以外的其他选择
藉由non-virtual interface首发实现template method模式。
这个流派主张virtual函数应该几乎总是private,这个流派的拥护者建议,较好的设计是保留healthvalue为public成员函数,但让它成为non-virtual,并调用一个private virtual函数进行实际工作。
class GameCharacter{public: int healthValue() const { int retval=dohealthValue();//做一些真正的工作 return retval; }private: virtual int dohealthValue()const//派生类可重新定义它 { ...//缺省算法,计算健康函数 }}
这一基本设计,也就是令客户通过public non-virtual成员函数间接调用private virtual函数,称为non-virtual interface(NVI)手法。它是所谓template method设计模式(与C++templates 并无关系)的一个独特表现形式,我把这个non-virtual函数称为virtual函数的外覆器(wrapper)。
优点:可以确保外覆器在一个virtual函数被调用之前设定好场景,并且在调用之后清理场景。“事前工作做”可包含锁定互斥器。制造运转日志及录像,验证class约束条件等,“事后工作”可以包括互斥器,解除锁定,验证函数的事后条件,再次验证class约束条件等等,如果让客户直接调用virtual函数,则没有这个优点。
由function pointer实现strategy模式class GameCharacter;//前置声明int defaultHealthcalc(cosnt GameCharacter&gc);class GameCharacter{public: typedef int (*HealthcalcFunc)(const GameCharacter&); explict GameCharacter(HealthcalcFunc hcf=defaultHealthCalc):healthFUnc(hcf){} int healthValue()const { return HealthFunc(*this);}private: HealthCalcFunc healthFunc; }}
这个做法是常见的strategy设计模式的简单应用,拿它和“基于GameCharacter”继承体系内之virtual函数比较,它提供了某些有趣的弹性:
- 同意任务类型的不同实体可以有不同的健康计算函数。
某已知任务的健康指数计算函数可以在运行期变更。
总结:①virtual函数的替代方案包括NVI手法和Strategy设计模式的多种形式,NVI手法是一个特殊形式的template method设计模式。
②将机能从成员函数移到class外部函数,带来的一个缺点是,非成员函数无法访问class的non-public成员。
Item36:绝不重定义继承来的non-virtual函数
item32说过所谓的public继承意味着is-a的关系,item34则指出为什么在class内声明一个non-virtual函数会为该class建立一个不变性,凌驾于特异性,如果你将这两个观点施行于两个classB和D以及non-virtual成员函数B:mf身上,那么:
- 适用于B对象的每一件事,也适用于D对象,因为每一个D对象都是一个B对象。
- B的derived class一定会继承mf的接口和实现,因为mf是B的一个non-virtual函数。
现在,如果D重新定义mf,你的设计便出现矛盾,如果D真的有必要实现出与B不同的mf,并且如果没一个D对象-不管有多么特化-真的必须使用D所提供的mf实现代码,那么“每一个D都是一个B”就不是真,既然如此,D就不该以public形式继承B。另一方面,如果D真的必须以public形式继承B,并且如果D真的需要实现出与B不同的mf,那么mf就无法为B反应出“不变性凌驾于特异性”的性质,既然这样mf应该什么为virtual函数,最后,如果每个D真的是一个B,并且如果mf真的为B反映出“不变性凌驾于特异性”的性质,那么D就不需要重新定义mf,而且它也不应该尝试这么做,不论是哪一种观点:任何情况下都不应该重新定义一个继承而来的non-virtual函数。
Item38:通过符合塑模出has-a或者“根据某物实现出”
Item39:明智而审慎地使用private继承
总结:①private继承意味着is-implementated-in-terms-of(根据某物实现出),它通常比private继承1 复合的级别低,但是当derived class需要访问protected base class的成员,或者重新定义继承而来的virtual函数时候,这么设计是合理的。
②和复合不同,private继承可以造成empty base class最优化,这对于致力于“对象尺寸最小化”的程序库开发者来说,可能很重要。
Item40:明智而审慎地使用多重继承
总结:①多重继承比单一继承更复杂,它可能导致新的歧义性,以及对virtual继承的需要。
②virtual继承会增加大小,速度,初始化复杂度等成本。如果virtual base classes不带任何数据,将是最具有使用价值的情况。
③多重继承的确有正常用途,其中一个情节涉及“public 继承某个interface class”和“private 继承自某个协助实现的class”的俩相组合。
- [Effective C++] 继承与面向对象设计
- 《Effective C++》继承与面向对象设计
- Effective C++(六)继承与面向对象设计
- Effective C++(六)继承与面向对象设计
- effective C++: 6.继承与面向对象设计
- Effective c++(笔记)之继承关系与面向对象设计
- Effective C++(六)继承与面向对象设计
- <<Effective C++>> 读书笔记6: 继承与面向对象设计
- 《Effective C++》第六章:继承与面向对象设计
- Effective C++ -- 继承与面向对象设计
- Effective C++读书笔记---继承与面向对象设计
- effective C++ 继承与面向对象设计 笔记
- Effective C++读书笔记 第六部分 继承与面向对象设计
- Effective C++ ——继承与面向对象设计
- Effective C++ 读书笔记(六) 继承与面向对象设计
- Effective C++ 6.继承与面向对象设计
- Effective C++ --6 继承与面向对象设计
- effective C++ 学习笔记 实现&&继承与面向对象设计
- MFC中如何隐藏RichEdit控件的光标
- 面试题40:查找数组中只出现一次的数字(2个)
- Java工程师面试总结--Struts2部分
- 中缀表达式转后缀表达式
- JS学习笔记——作用域链
- 《Effective C++》继承与面向对象设计
- Ubuntu Jdk卸载 Oracle Jdk安装
- UVA10917 Walk Through the Forest
- L1-040. 最佳情侣身高差 java
- 递归递推 G
- 【Python学习】python爬虫有道翻译的实现
- 解决android 中在沉浸式布局下,EditText输入框在界面底部,在弹出输入法时将顶部标题栏向上推出界面问题
- java中实现定时任务
- python中yield用法