Effective C++学习笔记(6)

目录

  • 条款32. 确定你的public继承塑模出is-a关系
  • 条款33.避免遮掩继承而来的名称
  • 条款34.区分接口继承和实现继承
  • 条款35.考虑virtual函数以外的其他选择
  • 条款36.绝不重新定义继承而来的non-virtual函数
  • 条款37.绝不重新定义继承而来的缺省参数值
  • 条款38.通过复合塑模出has-a或“根据某物实现出”
  • 条款39.明智而审慎地使用private继承
  • 条款40.明智而审慎地使用多重继承

条款32. 确定你的public继承塑模出is-a关系

is-a:表示一种关系,即public继承的子类对象应该也可以当作一种父类对象,适用于base classes身上的每一件事情一定也适用于derived classes身上,因为每一个derived class对象也都是一个base class对象。

条款33.避免遮掩继承而来的名称

问题:子类重写父类成员函数时,会覆盖原本应该继承的父类所有同名称的成员函数,破坏了public继承的“is-a”原则。
在这里插入图片描述

解决方法:可在子类定义中加入“using Base::functionname;”,使得父类Base中的名为“fuctionname”的所有函数(包括所有重载函数)在子类中曝光。
在这里插入图片描述
在这里插入图片描述

条款34.区分接口继承和实现继承

  • 接口继承和实现继承不同。在public继承之下, derived classes总是继承base class的接口
  • pure virtual函数只具体指定接口继承
  • impure virtual函数具体指定接口继承及缺省实现继承:在继承接口的同时,依然可以使用父类的接口实现,除非子类自己重写虚函数,但是要警惕当前子类是否能够安全使用父类默认接口实现。
  • non-virtual函数具体指定接口继承以及强制性实现继承:non-virtual函数的继承意味着可能需要在子类中重写该接口函数,因此需要自己对接口重新实现。

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

  • 代替方法1:NVI(non-virtual interface)手法,令客户通过public non-virtual成员函数间接调用private virtual函数。其中,non-virtual成员函数被成为 virtual函数函数的外覆器(wrapper)。外覆器可以确保在一个virtual函数被调用之前设定好适当的场景,并在调用结束之后进行清理工作。
    在这里插入图片描述        在NVI手法下 virtual函数也可以是protected。某些class继承体系要求derived class在 virtual函数的实现内必须调用其base class 的对应兄弟,而为了让这样的调用合法,virtual函数必须是protected,不能是private。
            有时候virtual 函数甚至一定得是public(例如具备多态性质的base classes的析构函数—见条款7),这么一来就不能实施NVI手法了
  • 代替方法2:将virtual函数替换为”函数指针成员变量。在类中声明一个函数指针成员变量,用于接收不同行为的非成员函数地址,并在构造函数中进行初始化。为了解决非成员函数无法访问成员变量的问题,可以建立friend关系或者调用public成员函数获取信息。
    在这里插入图片描述
  • 代替方法3:用std::function代替上述函数指针,将会得到一个更加”泛化的指针“,因为它可以自动进行隐式转换,而函数指针固定类型后就无法改变。
    在这里插入图片描述

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

原因:当一个指向子类对象的指针调用被重写的non-virtual函数时,调用父类还是子类的non-virtual函数并不取决于对象是子类对象还是父类对象,而是取决于最初指针声明的类型。此外,我们也应当遵守适用于基类对象的每一件事,也适用于继承类对象;基类的派生类一定会继承non-virtual的接口和实现。

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

原因:缺省参数值都是静态绑定,而virtual函数是动态绑定。
静态类型:被声明时采用的初始类型;
动态类型:目前所指对象的类型。
虚函数调用哪一个取决于动态类型是哪一个对象。
而缺省参数值取决于静态类型。
        如果为了实现多态用基类Shape指针指向派生类对象,那么用基类指针调用虚函数draw时,默认参数还是取决于基类的默认参数,而非派生类对象的默认参数。
在这里插入图片描述
由于虚函数大概率会在派生类中被重写,但是其默认参数必须与基类虚函数默认参数保持一致。后续如果需要修改默认参数,那么基类以及所有派生类的该默认参数均要被手动一一修改。可采用前面阐述的NVI方法来实现统一虚函数的默认参数:
在这里插入图片描述

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

  • 在应用领域,复合表示has-a(有一个):用一个复合类对象由多个子对象组合而成。
    在这里插入图片描述

  • 在实现领域,符合表示is-implemented-in-terms-of(根据某物实现出):用list实现set。
    在这里插入图片描述

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

  • 如果classes之间的继承关系是private,编译器不会自动将一个derived class对象转换为个base class对象;由private base class继承而来的所有成员,在 derived class中都会变成private属性,纵使它们在base class 中原本是protected 或public属性。
  • Private继承意味is-implemented-in-terms of(根据某物实现出)。它通常比复合( composition)的级别低。
  • 两个类不存在”is-a“关系时,并且derived class需要访问protected base class 的成员,或需要重新定义继承而来的 virtual函数时,那么就可以使用private继承。
  • 和复合( composition)不同,private继承可以造成empty base最优化。这对致力于“对象尺寸最小化”的程序库开发者而言,可能很重要。如果用复合则会造成对象嵌套,浪费空间;而私有继承在保证可以使用基类的成员前提下,尽可能减少占有的空间。(实例化一个没有非静态成员变量、没有虚函数的”空类“(empty class)也会被分配1个字节的空间,而继承空类将不会浪费空间)(目前感觉这一点还未体现得很明显)
  • 复合和private继承都意味 is-implemented-in-terms-of,但复合比较容易理解,所以无论什么时候,只要可以,你还是应该选择复合

条款40.明智而审慎地使用多重继承

  • 多重继承比单一继承复杂。它可能导致新的歧义性(不同基类有同名成员),以及对virtual继承的需要。
  • virtual继承会增加大小(虚指针)、速度(指针索引)、初始化(及赋值)复杂度等等成本。如果virtualbase classes不带任何数据,将是最具实用价值的情况。
  • 多重继承的确有正当用途。其中一个情节涉及“public继承某个Interface class”和“private继承某个协助实现的class”的两相组合。
    在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/3356.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

spring-boot-starter-parent 与 spring-boot-dependencies

Spring Boot的每个发布版本都会规划它所支持的依赖项。实际上,你不用指定这些依赖项的版本号,因为Spring Boot都为你管理好了。当更新Spring Boot时,会相应的更新依赖。 Maven管理依赖 Maven用户可以继承spring-boot-starter-parent项目&am…

OpenMP并行化傅里叶变换

设计思想 傅里叶变换,表示能将满足一定条件的某个函数表示成三角函数(正弦和/或余弦函数)或者它们的积分的线性组合。在不同的研究领域,傅里叶变换具有多种不同的变体形式,如连续傅里叶变换和离散傅里叶变换。 快速傅…

windows各种文件操作、系统相关的命令行脚本

目录 写在前面文件操作命令说明遍历文件并写进txt按行读取txt并文件计数文件重命名 参考完 写在前面 1、本文内容 windows各种文件操作、系统相关的命令行脚本 请保存为.bat运行 2、平台 windows10 3、转载请注明出处: https://blog.csdn.net/qq_41102371/article/…

《零基础入门学习Python》第047讲:魔法方法:定制序列

0. 请写下这一节课你学习到的内容:格式不限,回忆并复述是加强记忆的好方式! 常言道:“无规矩不成方圆”,讲的是万事万物的发展都要在一定的规则下去运行,只有遵循一定的协议去做,事情才能够按照…

如何将一个目录下的所有md文件导出成pdf

要将一个目录下的所有Markdown(.md)文件导出为PDF,您可以使用Node.js进行编程来实现。以下是一种可能的方法: 首先,您需要设置Node.js环境并安装依赖项。在命令行中导航到您的项目目录,并运行以下命令&…

前端js防抖

一、原生js防抖 <!DOCTYPE html> <html> <head><title>防抖按钮示例</title> </head> <body><button id"immediateButton">立即触发</button><button id"waitButton">等候触发</button&g…

Stream实现List和Map互转总结

本文来说下Stream实现List和Map互转总结 文章目录 实体类Map转List代码List转Map代码 实体类 本篇介绍Stream流List和Map互转&#xff0c;同时在转换过程中遇到的问题分析。 package cn.wideth.collect;import lombok.AllArgsConstructor; import lombok.Data; import lombok.N…

GAMES101作业2

文章目录 作业内容Step 1. 创建三角形的2维bounding boxStep 2. 判断bBox中的像素中心点是否在三角形内Step 3. 比较插值深度和Depth BufferMSAA 作业内容 在屏幕上画出一个实心三角形&#xff0c; 换言之&#xff0c;栅格化一个三角形。上一次作业中&#xff0c;在视口变化之…

二次元少女-InsCode Stable Diffusion 美图活动一期

一、 Stable Diffusion 模型在线使用地址&#xff1a; https://inscode.csdn.net/inscode/Stable-Diffusion 二、模型相关版本和参数配置&#xff1a; 模型版本&#xff1a;chilloutmix_NiPrunedFp32Fix.safetensors 采样方法(Sampler)Sampling method&#xff1a;DPM SDE …

2023年经典【自动化面试题】附答案

一、请描述一下自动化测试流程&#xff1f; 自动化测试流程一般可以分为以下七步&#xff1a; 编写自动化测试计划&#xff1b; 设计自动化测试用例&#xff1b; 编写自动化测试框架和脚本&#xff1b; 调试并维护脚本&#xff1b; 无人值守测试&#xff1b; 后期脚本维…

C#如何控制IIS动态添加删除网站详解

目的是在Winform程序里面&#xff0c;可以直接启动一个HTTP服务端&#xff0c;给下游客户连接使用。 查找相关技术&#xff0c;有两种方法&#xff1a; 1.使用C#动态添加网站应用到IIS中&#xff0c;借用IIS的站群软件管理能力来提供HTTP接口。本文即对此做说明 2.在Winform…

【UE4 塔防游戏系列】07-子弹对敌人造成伤害

目录 效果 步骤 一、让子弹拥有不同伤害 二、敌人拥有不同血量 三、修改“BP_TowerBase”逻辑 四、发射的子弹对敌人造成伤害 效果 步骤 一、让子弹拥有不同伤害 为了让每一种子弹拥有不同的伤害值&#xff0c;打开“TotalBulletsCategory”&#xff08;所有子弹的父类…

【Spring Boot】Web开发 — Web开发简介

Web开发简介 首先介绍Spring Boot 提供的Web组件spring-boot-starter-web&#xff0c;然后介绍Controller和RestController注解&#xff0c;以及控制数据返回的ResponseBody注解&#xff0c;最后介绍Web配置&#xff0c;以便让读者对使用Spring Boot开发Web系统有初步的了解。…

linux下一个iic驱动(按键+点灯)-互斥

一、前提&#xff1a; 硬件部分&#xff1a; 1. rk3399开发板&#xff0c;其中的某一路iic&#xff0c;这个作为总线的主控制器 2. gd32单片机&#xff0c;其中的某一路iic&#xff0c;从设备。主要是按键上报和灯的亮灭控制。&#xff08;按键大约30个&#xff0c;灯在键的…

送呆萌的她一个皮卡丘(Python实现)

目录 1 呆萌的她 2 思维需要革新 3 送她的一个漂亮皮卡丘 4 Python完整代码奉上 1 呆萌的她 又是一季春风暖阳下, 你是一湾一湾羞涩的春波。 静静感受着&#xff0c; 你垂下的枝膊 在我的脸上轻轻抚摸 一对春燕,低低掠过 涟漪乍起&#xff0c;是你浅浅的笑窝...... 2 思…

(五)「消息队列」之 RabbitMQ 主题(使用 .NET 客户端)

0、引言 先决条件 本教程假设 RabbitMQ 已安装并且正在 本地主机 的标准端口&#xff08;5672&#xff09;上运行。如果您使用了不同的主机、端口或凭证&#xff0c;则要求调整连接设置。 获取帮助 如果您在阅读本教程时遇到问题&#xff0c;可以通过邮件列表或者 RabbitMQ 社区…

56 # 实现 pipe 方法进行拷贝

pipe 是异步的&#xff0c;可以实现读一点写一点&#xff0c;管道的优势&#xff1a;不会淹没可用内存&#xff0c;但是在导入的过程中无法获取到内容 const fs require("fs"); const path require("path");fs.createReadStream(path.resolve(__dirname…

前端 | (七)浮动 | 尚硅谷前端html+css零基础教程2023最新

学习来源&#xff1a;尚硅谷前端htmlcss零基础教程&#xff0c;2023最新前端开发html5css3视频 文章目录 &#x1f4da;浮动介绍&#x1f407;元素浮动后的特点&#x1f407;浮动小练习&#x1f525;盒子1右浮动&#x1f525;盒子1左浮动&#x1f525;所有盒子都浮动&#x1f5…

Python 闭包 装饰器

闭包定义&#xff1a;在函数嵌套的前提下&#xff0c;内部函数使用了外部函数的变量&#xff0c;并且外部函数返回了内部函数&#xff0c;我们把这个使用外部函数变量的内部函数称为闭包. 下面实现一个在执行方法的前后打印日志的场景 第一种方法装饰器 1.定义外层函数(要求…

vscode 添加 ros头文件

解决 vscode不能支持ROS相关头文件和没有智能提示问题 vscode 编写pakage源文件代码,#include<ros/ros.h>等头文件时报错,无法运行智能提示 1.vscode中CTRL+P 2.键入ext install ms-iot.vscode-ros 按回车,等待下载ros插件 3.修改c_cpp_properties.json文件 鼠标…