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

news/2024/11/22 16:30:53/
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继承某个接口类"和"私有继承某个协助实现的类"的组合(类适配器)。
     

 


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

相关文章

c语言进阶部分详解(《高质量C-C++编程》经典例题讲解及柔性数组)

上篇文章我介绍了介绍动态内存管理 的相关内容:c语言进阶部分详解(详细解析动态内存管理)-CSDN博客 各种源码大家可以去我的github主页进行查找:唔姆/比特学习过程2 (gitee.com) 今天便接“上回书所言”,来介绍《高质…

AD教程(六)现有元件模型的调用

AD教程(六)现有元件模型的调用 导入现有原理图 Altium Schematic Document (.SchDoc) 直接拖入AD即可 直接用现有原理图生成原理图库 点击设计,选择生成原理图库,进入归类设置界面(用原理图直接生成原理图库&#xf…

docker 安装 minio (单体架构)

文字归档:https://www.yuque.com/u27599042/coding_star/qcsmgom7basm6y64 查询 minio 镜像 docker search minio拉取镜像 docker pull minio/minio创建启动 minio 容器 用户名长度至少为 3,密码长度至少为 8 docker run \ -p 9000:9000 \ -p 9090:909…

linux配置vlan后网络不通

如果在Linux上配置了VLAN,但网络不通,这可能是由于多种原因导致的。以下是一些可能的原因和解决方法: 检查物理连接:首先,确保VLAN支持的物理网络连接正常。确保网络电缆连接正确,交换机端口配置正确&#…

bug: https://aip.baidubce.com/oauth/2.0/token报错blocked by CORS policy

还是跟以前一样,我们先看报错点:(注意小编这里是H5解决跨域的,不过解决跨域的原理都差不多) Access to XMLHttpRequest at https://aip.baidubce.com/oauth/2.0/token from origin http://localhost:8000 has been blo…

基于layui的select选择框修改为多选框

layui-xm-select 的功能强大,可多选、可下拉树、下拉日期多选、下拉折叠面板、下拉穿梭框、级联模式。 首先在引用layui css和js 的基础上,再引用js:layui-xm-select layui-xm-select点击下载地址 基本使用 第一步: 下载 第二步: 引入 layu…

Macos下安装使用Redis

Redis 是一个基于内存的key-value的结构数据库适合存储热点数据 Macos安装Redis https://redis.io/docs/getting-started/installation/install-redis-on-mac-os/安装redis brew install redis查看安装信息: brew info redis前台启动redis: redis-server后台启…

PCL 计算一个平面与包围盒体素的相交线

文章目录 一、简介二、实现代码三、实现效果参考资料一、简介 基于之前计算的包围盒体素(PCL 包围盒体素化显示),这里使用一个平面与其进行相交,并求出与其中体素单元的相交线。 二、实现代码 //标准文件 #include <iostream> #include <thread>//PCL