《Effective C++》继承与面向对象设计
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++ —— 继承与面向对象设计(六)
条款32 : 确定你的public继承塑模出is-a关系 以C++进行面向对象编程,最重要的一个规则是:public inheritance(公开继承)意味“is-a”(是一种)的关系.请务必牢记.当 ...
- Effective C++ -- 继承和面向对象设计
32.确保你的public继承了模is-a关系 public继承意味着is-a关系(里氏替换原则),一切适用于基类也适用于派生类. 矩形继承正方形问题: 可实施与矩形的操作无法实施与正方形 在编程领域 ...
- Effective C++ ——继承与面向对象设计
条款32:确定你的public继承塑模出is-a关系 以public继承的类,其父类的所有的性质都应该使用与子类,任何需要父类的地方都应该能用子类来代替,任何子类类型的对象也同时是父类的: class ...
- EffectiveC++ 第6章 继承与面向对象设计
我根据自己的理解,对原文的精华部分进行了提炼,并在一些难以理解的地方加上了自己的"可能比较准确"的「翻译」. Chapter 6 继承与面向对象设计 Inheritance and ...
- Effective C++(20) 继承与面向对象设计
本文主要参考<Effective C++ 3rd>中的第六章部分章节的内容. 关注的问题集中在继承.派生.virtual函数等.如: virtual? non-virtual? pure ...
- Effective C++: 06继承与面向对象设计
32:确定你的public继承塑模出is-a关系 以C++进行面向对象编程,最重要的一个规则是:public继承表示的是"is-a"(是一种)的关系. 如果令class D以pub ...
- Effective C++ 6.继承与面向对象设计
//条款32:确定你的public继承塑模出is-a关系 // 1.public继承意味着is-a的关系,适用在基类上的方法都能用于派生类上. //条款33:避免遮掩继承而来的名称 // 1.在pub ...
- Effective C++笔记:继承与面向对象设计
关于OOP 博客地址:http://www.cnblogs.com/ronny 转载请注明出处! 1,继承可以是单一继承或多重继承,每一个继承连接可以是public.protected或private ...
- Effective C++笔记(六):继承与面向对象设计
参考:http://www.cnblogs.com/ronny/p/3756494.html 条款32:确定你的public继承塑模出is-a关系 “public继承”意味着is-a.适用于base ...
- 【Effective C++】继承与面向对象设计
关于OOP 1,继承可以是单一继承或多重继承,每一个继承连接可以是public.protected或private,也可以是virtual或non-virtual. 2,成员函数的各个选项:virtu ...
随机推荐
- String类型变量的使用
1.String属于引用数据类型,翻译为:字符串 2.声明String类型变量时,使用一对"" 3.String可以和8种基本数据类型变量做运算,且运算只能是连接运算:+ 4.运算 ...
- C语言之走迷宫深度和广度优先(利用堆栈和队列)
完成以下迷宫 利用二维数组储存每一个数组里的值,若是不能走则为1,若是可行就是0,走过了就设为2. 一般是再复制一个数组,用来记录. 堆栈的思想就是将一个点的上下左右都遍历一遍,若可行进栈,跳出遍历, ...
- 知识图谱-生物信息学-医学论文(Chip-2022)-BCKG-基于临床指南的中国乳腺癌知识图谱的构建与应用
16.(2022)Chip-BCKG-基于临床指南的中国乳腺癌知识图谱的构建与应用 论文标题: Construction and Application of Chinese Breast Cance ...
- 10.APIView视图
from rest_framework import status from rest_framework.response import Response from snippets.models ...
- 现代 CSS 指南 -- at-rule 规则扫盲
大部分同学都用过 CSS 的屏幕宽度媒体查询,像是这样: @media screen and (min-width: 900px) { div { padding: 1rem 3rem; } } 这里 ...
- 2022HNCTF--WEB
@ 目录 [Week1]Interesting_http 分析 payload [Week1]2048 分析 payload [Week1]easy_html 分析 paylaod [Week1]In ...
- xss学习笔记(萌新版)
xss简介 xss攻击者构造恶意信息然后在用户的浏览器上执行,主要分为反射性xss,这种主要是某个页面存在有漏洞的参数,然后填上恶意参数把整个链接发给用户或者管理员,他们点击了带有恶意参数的链接就会执 ...
- onps栈使用说明(1)——API接口手册
1. 底层API 由协议栈底层提供的api,用于涉及底层操作的一些功能实现,这些api接口函数的原型定义分布于不同的文件,它们被统一include进了onps.h中: open_npstack_loa ...
- Armv8之Execution State 和 Exception Level(一)
@ 目录 1. 典型的Exception Level使用模型 2.异常相关术语 3. Execution State 3.1 两种Execution State 3.2 决定Execution Sta ...
- 剖析一下"抢茅台"脚本底层逻辑
本文作者:梁东东 前言: 今天你撸茅台了么? 撸茅台已经成为社会现象,茶余饭后讨论的最佳实践 2022年双十一大促已经完美收官,兄弟姐妹克服种种困难与挑战.. 备战的会议室忙碌中带着紧张,当峰值过后的 ...