EC35

news/2024/11/29 10:45:39/

35. 考虑virtual函数以外的其他选择

  • 令客户通过public non-virtual成员函数间接调用private virtual函数。
  • 继承类可以重新定义继承而来的private virtual函数
  • 该条款主要介绍替代virtual函数的方法,主要有:
    1)用private virtual函数替代:即原本用virtual函数地方改成用非virtual函数,并在这里面调用private virtual函数。
    2)用函数指针替换virtual函数,(同一函数指针是要求返回值类型+参数列表个数和类型相同),继承类对该函数指针可以有不同的定义即可(即定义拥有相同返回值类型和参数列表个数和类型的函数),从而发挥virtual函数作用
    3)用tr1::function替代virtual函数。这个和函数指针区别在于tr1::function支持返回值+参数列表的隐式转换。

总结:该条款介绍了替代virtual函数方式,但我没想明白我们是出于什么考虑不选择用virtual函数,而选择用这些替代方法。
从条款37内容看,似乎是出于这样的考虑:缺省参数值的virtual函数是静态绑定的,如果想不重复定义继承而来的缺省参数值的virtual函数,并同时提供缺省参数值给基类和继承类的用户,即保证在基类和继承类中缺省参数值的virtual函数相同。如果基类的缺省参数值改变,那么这些继承类也必须改变,否则就编变成了重复定义继承而来的缺省参数值的virtual值,这时候就需要替代virtual函数。即用这些替代方式替代缺省参数值的virtual函数

36. 绝不重新定义继承而来的non-virtual函数

  • non-virtual函数是静态绑定的,virtual函数是动态绑定的。

    class B
    {public:void mf();
    }class D: public B
    {public:void mf();
    }D x;
    B *pB = &x;
    pB->mf(); // 1D *pD = &x;
    pD->mf(); // 2
    

    若mf是non-virtual函数,那么1调用的是B的mf,2调用的D的mf,因为这是静态绑定,在编译期间就固定了。(也就是之前说的遮蔽问题)

    若mf是virtual函数,那么1和2调用的是D的mf,因为pB和pD真正指的是类型为D的对象。

总结:绝对不要重新定义继承而来的non-virtual函数,因为这样会为基类反映“不变性凌驾特性”的性质。导致指向继承类的基类指针调用的成员函数是基类的而不是继承类的。

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

  • virtual函数是动态绑定的,而virtual缺省参数值却是静态绑定的。
    动态绑定是调用一个virtual函数,究竟调用哪一份函数实现代码,取决于发出调用的那个对象的动态类型。即等号右边的类型。
    静态绑定是调用一个virtual缺省参数值(即有默认参数值),是取决于等号左边的类型。
  • c++如此运作的原因是——运行期效率。

总结:绝不重新定义继承而来的缺省参数值(即有默认参数值)的virtual函数,因为其是静态绑定的。

38. 通过复合塑模出has-a或“根据某物实现出”

  • 复合是类型之间的一种关系,即当某种类型的对象内含该种类型的对象,就是这种关系。
  • 复合这个术语有这些同义词:layering(分层)、containment(内含)、aggregation(聚合)和embedding(内嵌)
  • 复合意味着有一个或根据某物实现出,当需要在软件中处理两个不同的领域。当复合发生于应用域内的对象之间,表现出has-a的关系;当其发生在实现域内则表现根据某物实现出。
  • 当不知道是选择is-a还是has-a时候,想想is-a的定义:如果D是一种B,对B为真的每一件事对D也都应该为真。

总结:复合的意义和public继承完全不同,当不知道选择is-a还是复合的has-a或is-implemented-in-terms-of时,想想is-a的定义以及复合的定义,如果是该对象要做另外个领域的事情,那么应该选择用复合。

例如自己定义一个set模板,就应该复合list而不是public继承list,因为list不支持只存储不重复数据。

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

  • private继承并不意味这is-a关系,意味着implement-in-terms-of(根据某物实现出)。即如果要D以private形式继承B,用意就是采用B内已经备好的某些特性。尽可能用复合,必要时用private继承。【必要时指的是protected成员和/或virtual函数牵扯进来时候】
  • private继承意味着只继承实现部分,没有继承接口部分。即其在软件“设计”层面没有意义,其意义在软件实现层面。
  • private继承有两条规则:
    1)classes之间的继承关系是private时,编译器不会自动将一个继承类对象转为基类对象。
    2)由基类private继承而来的所有成员,在继承类中都会变成private属性。
  • private继承主要用于当一个意欲成为继承类想访问一个意欲成为基类的protected部分,或为了重新定义一个或多个virtual函数。
  • private继承可以造成empty base最优化。

总结:虽说private继承也能体现复合的一种,但是能用复合就不用private继承,除非遇到要重新定义继承而来的virtual函数或继承类要访问基类的基类protected成员。


http://www.ppmy.cn/news/112820.html

相关文章

React 使用recharts实现散点地图

一、前端框架reactant design UI二、首先安装recharts npm install recharts 或者 yarn add recharts 三、引入插件及chinaJSON.js(里面有经纬度信息)下载百度云网盘地址:chinaJSON.js 提取码:ep30由于项目需要我是全部存数据库的&#xff0c…

(BDCI-CCF)出租车发票识别

参考文章: ​​​​​​百度AI攻略:出租车票识别_才能我浪费的博客-CSDN博客 附完整python源码)基于tensorflow、opencv的入门案例_发票识别一:关键区域定位_小白来搬家-CSDN博客_python发票识别 注:感谢一起完成项目…

2021-05-31

Linux DRM那些事-libdrm调试准备 本文主要介绍libdrm的代码下载、编译和调试前的准备工作。 一、代码下载 libdrm下载网址:https://dri.freedesktop.org/libdrm/libdrm-2.4.89.tar.bz2 解压命令:tar -jxvf libdrm-2.4.89.tar.bz2 在代码解压后&…

03

术语表 术语 定义 敏感数据 敏感数据的具体范围取决于产品具体的应用场景,产品应根据风险进行分析和判断。典型的敏感数据包括口令、银行帐号、大批量个人数据、用户通信内容和密钥等。一类如果丢失或者泄漏,会对数据的所有者造成负面影响的数据。 本…

20070523

休息了几天(其实也不算休息,基本上按时下班走人) 今天把活作了 估计会晚走 昨晚玩到快2点 。。。。 疯了。。。 拟或是冲动了?

EC 三

8>.debug message ECdebug的方式很多,类似于RW的方式,通过外接的工具,debugger和debuggee,把当前 Registers,memory里的值都读出来,拿来和FW或者DS里面对比,看是不是正确,也可以抛一些断点,然后回看registers里有没有改变.呵,这是一个细致又烦锁的活. 就我所知ITE85X…

23种设计模式之创建型模式(单例、工厂方法、抽象工厂、生成器和原型模式)

概述 设计模式是针对某一类问题的最优解决方案,是从许多优秀的软件系统中总结出的。 Java中设计模式(java design patterns)通常有23种。 模式可以分成3类:创建型、行为型和结构型。 创建型模式 创建型模式涉及对象的实例化&#…

PL/SQL之索引和分区

一、索引 --index 数据库中的索引和目录的概念类似,如果某个列出现在查询的条件中,而该列的数据是无序的,那么查询时只能一行一行去扫描。 创建索引就是对某些特定列中的数据进行排序,生成独立的索引表, 当在某个…