[Effective C++]条款36-37 两个绝不
本文初发于 “天目中云的小站”,同步转载于此。
条款36 : 绝不重新定义继承而来的non-virtual函数
本条款很容易理解, 援引以前的条款就可以说明为什么 :
-
条款34中就提到过 : non-virtual函数意味着接口 + 强制性实现继承, 它不应当被改变.
-
重新定义继承而来的non-virtual函数会触发条款33中所说的遮掩机制.
-
触发遮掩机制其实是对条款32中"public意味着is-a"这个定理的破坏.
如果你这么做了, 还可能会出现以下奇怪的效果 :
class B {
public:void mf();...
};
class D: public B { // D派生自B
public:void mf(); // 这个定义遮掩了B中的mf()
}; //--------------------------------------------//D x; // 创建一个D对象B *pB = &x;
pB->mf(); // 调用B::mf()D *pD = &x;
pD->mf(); // 调用D::mf()
我们可以看到通过同一个对象D调用的mf()
居然效果不同, 这也很容易理解, 毕竟non-virtual并没动态绑定, 只是依据当前对象的静态类型来调用的.
请记住 :
- 任何情况下都不应重新定义一个继承来的non-virtual函数.
条款37 : 绝不重新定义继承而来的缺省参数值
先缩小本条款的范围, 通过条款36我们首先应该知道不应该修改继承来的non-virtual函数, 所以本条款的讨论范围将局限在"继承一个带有缺省参数的virtual函数".
首先明确本条款的核心知识 :
- virtual函数本身是动态绑定的, 但是缺省参数值是静态绑定的.
简单理解就是virtual函数会根据对象的当前类型进行动态绑定, 而缺省值无法改变, 只和一开始定义的静态类型相关.
我们来看代码来理解 :
class Shape {
public:enum ShapeColor { Red, Green, Blue }; virtual void draw(ShapeColor color = Red) const = 0; // Shape默认缺省值为Red...
};class Rectangle: public Shape {
public:// 这是一个糟糕的写法!virtual void draw(ShapeColor color = Green) const; // Shape默认缺省值为Green, 但是有用吗?...
};class Circle: public Shape {
public:virtual void draw(ShapeColor color) const; // 无缺省值...
};
这里设计了一个Shape基类, 派生出三角和圆, 我们来看调用时会发生什么 :
// 以下的静态类型都是基类
Shape* ps;
Shape* pc = new Circle;
Shape* pr = new Rectangle; pc->draw();
pr->draw();
这样子调用看上去没有任何问题, 实际上也确实依靠动态绑定调用到了派生类对应的draw(), 但根据测试pc->draw()
中color缺省值是Red而非Green, 这便是因为我们上述的理由, 缺省值看的是静态类型, 也就是Shape.
-
为什么C++会设计成会这样?
其实是因为动态绑定缺省值的花销实在过大, C++为了效率做了这般取舍.
由此引发出的另一个问题
- 当静态类型是派生类时, 将无法获取基类的缺省值!
// 这样可以使用基类的缺省值
Shape* pc = new Circle;
pc->draw();// 这样不行!
Circle* cc = new Circle;
cc.draw(); // 错误, 自己没有缺省值, 并且也调不到基类的缺省值
于是这样的机制似乎在逼迫我们要把所有含缺省值的virtual函数都手动填上和基类一样的缺省值, 就像下面的代码一样 :
class Shape {
public:enum ShapeColor { Red, Green, Blue }; virtual void draw(ShapeColor color = Red) const = 0;...
};class Rectangle: public Shape {
public:virtual void draw(ShapeColor color = Red) const; // 都加上和基类相同的缺省值...
};class Circle: public Shape {
public:virtual void draw(ShapeColor color = Red) const; // 都加上和基类相同的缺省值...
};
只有这样你才可以确保在任何使用场景下你的缺省值都可以正常生效.
但是这样值得吗? 显然是不值得的, 这里包含了代码重复和代码相依性两大弊病, 只要你想修改基类中的缺省值, 那么其他所有的派生类就都要修改, 这是我们非常不希望看到的, 还好我们有一个现成的解决方法.
藉由NVI手法解决上述问题
没错, 就是我们条款35详细介绍的NVI手法(没看过的可以看我往期博客的对应部分, 这将很影响下文的理解), 我们让非虚函数接口有缺省值, 如果有缺省情况, 把这个缺省值传入具体实现的虚函数就可以了! 代码如下 :
class Shape {
public:enum ShapeColor { Red, Green, Blue };void draw(ShapeColor color = Red) const // 非虚函数接口(包含缺省值), 见条款35{doDraw(color); // 具体实现的虚函数接受color}...
private:virtual void doDraw(ShapeColor color) const = 0; // 见条款35
}; class Circle: public Shape {
public:...
private:virtual void doDraw(ShapeColor color) const; // 这样就不必再加缺省值了! ...
};//-----------------------//Circle* cc = new Circle;
cc.draw(); // 这样的调用也被允许了!
请记住 :
- 绝对不要重新定义一个继承而来的缺省参数值, 因为它是静态绑定的.
- 再想让virtual函数携带缺省值是, 不妨使用NVI手法, 让非虚接口替虚函数携带缺省值.
by 天目中云
相关文章:
[Effective C++]条款36-37 两个绝不
本文初发于 “天目中云的小站”,同步转载于此。 条款36 : 绝不重新定义继承而来的non-virtual函数 本条款很容易理解, 援引以前的条款就可以说明为什么 : 条款34中就提到过 : non-virtual函数意味着接口 强制性实现继承, 它不应当被改变. 重新定义继承而来的non-…...
MySQL数据库——复制表数据与结构
命令格式 create table 表名 select 字段1,字段2 from 被复制表 首先新建一个表,然后从被复制的表中选择字段复制到新表 举例...
一文掌握如何编写可重复执行的SQL
一文掌握如何编写可重复执行的SQL 文章已同步个人博客:一文掌握如何编写可重复执行的SQL 背景 先提出问题,这里的可重复执行是指什么?我们为什么要编写可重复执行的sql? 可重复执行是指一条sql重复多次执行都不会报错…...
编译笔记:vs 中 正在从以下位置***加载符号 C# 中捕获C/C++抛出的异常
加载符号 解决方法: 进入VS—工具—选项----调试----符号,看右边有个“Microsoft符号服务器”,将前面的勾去掉,(可能还有删除下面的那个缓存)。 参考 C# 中捕获C/C抛出的异常 在需要捕捉破坏性异常的函数…...
[搜广推]王树森推荐系统——Deep Retrieval 召回
Deep Retrieval 简介 Deep Retrieval 是一种推荐系统框架,它将物品表示为路径(path),并在线上查找与用户最匹配的路径。 这种方法与传统的双塔模型不同,后者通常将用户和物品表示为向量,并在线上进行最近邻…...
【深入解析蓝牙dumpsys bluetooth_manager 命令输出】
了解蓝牙的工作状态以及如何在测试中利用这些信息。 1. Bluetooth Status(蓝牙状态) enabled: true state: ON address: 00:00:00:00:43:36 name: 小米手机 time since enabled: 00:15:18.492enabled: true — 蓝牙功能已启用。state: ON — 蓝牙目前是开启状态。address: …...
【三】Fast-DDS hello world!
编译hello world # 进入到源码目录 mkdir -p examples/cpp/hello_world/build cd examples/cpp/hello_world/build cmake .. && make -j4运行publisher ./hello_world publisher 运行subscriber ./hello_world subscriber 结果...
将HTML转换为PDF:使用Spire.Doc的详细指南(一) 试用版
目录 引言 1. 为什么选择 Spire.Doc? 1.1 主要特点 1.2 适用场景 2. 准备工作 2.1 引入 Spire.Doc 依赖 2.2 禁用 SSL 证书验证 3. 实现功能 3.1 主类结构 3.2 代码解析 4. 处理图像 5. 性能优化 5.1 异步下载图像 示例代码 5.2 批量处理优化 示例代…...
【物联网技术与应用】实验10:蜂鸣器实验
实验10 蜂鸣器实验 【实验介绍】 蜂鸣器是音频信号装置。蜂鸣器可分为有源蜂鸣器和无源蜂鸣器。 【实验组件】 ● Arduino Uno主板* 1 ● USB数据线* 1 ● 有源蜂鸣器* 1 ● 无源蜂鸣器* 1 ● 面包板* 1 ● 9V方型电池* 1 ● 跳线若干 【实验原理】 如图所示&#x…...
【python高级】342-TCP服务器开发流程
CS模式:客户端-服务端模式 TCP客户端开发流程介绍(五步)(C端) 1.创建客户端套接字对象 2.和服务端套接字建立连接 3.发送数据 4.接收数据 5.关闭客户端套接字 TCP服务端开发流程(七步)…...
C++开源项目 VLC 源代码的交叉编译以及库的裁剪方法详解
目录 1、VLC简介 2、VLC编译环境配置 2.1、编译环境 2.2、编译环境配置 2.2.1、下载安装MSYS2 2.2.2、下载mingw-w64 3、编译VLC 4、VLC库的裁剪 5、总结 C软件异常排查从入门到精通系列教程(核心精品专栏,订阅量已达600多个,欢迎订…...
draw.io 导出svg图片插入word后模糊(不清晰 )的解决办法
通常我们将图片从draw.io导出为svg格式后插入word, 会发现字体不清晰,特别是使用宋体时,折腾了半天,得到如下办法: 方法1: 在draw.io中导出pdf文件,使用 PDF转SVG转换器 - SVGConverter 将其转换为svg, 完美呈现。 …...
详解js柯里化原理及用法,探究柯里化在Redux Selector 的场景模拟、构建复杂的数据流管道、优化深度嵌套函数中的精妙应用
目录 详解js柯里化原理及用法,探究柯里化在Redux Selector 的场景模拟、构建复杂的数据流管道、优化深度嵌套函数中的精妙应用 一、什么是柯里化? 1、原理解析 2、一个直观的例子 二、如何实现柯里化? 1、底层实现 2、工作原理解析 3…...
Cesium材质——Material
简介: Cesium.Material对象的目的,就是生成一段名称为czm_getMaterial的函数(示例代码如下), 这个czm_getMaterial函数,是shader代码,会被放到片元着色器中使用。 czm_material czm_getMater…...
《点点之歌》“意外”诞生记
世界是“点点”的,“点点”是世界的。 (笔记模板由python脚本于2024年12月23日 19:28:25创建,本篇笔记适合喜欢诗文的coder翻阅) 【学习的细节是欢悦的历程】 Python 官网:https://www.python.org/ Free:大咖免费“圣经”教程《 …...
统计某个文件中某个字符串出现的次数
要统计某个文件中某个字符串出现的次数,有多种方法可以实现。以下是几种常用且高效的 Linux 命令方法: 方法一:使用 grep 和 wc 命令示例: grep -o "字符串" 文件名 | wc -l说明: grep -o "字符串&…...
C++简明教程(文章要求学过一点C语言)(3)
一、编程工具大揭秘——IDE 当我们准备踏入 C 编程的奇妙世界时,首先要认识一个重要的“魔法盒子”——集成开发环境(IDE)。IDE 就像是一个全能的编程工作室,它把我们写代码所需要的各种工具都整合到了一起,让编程这件…...
Springboot高并发乐观锁
Spring Boot分布式锁的主要缺点包括但不限于以下几点: 性能开销:使用分布式锁通常涉及到网络通信,这会引入额外的延迟和性能开销。例如,当使用Redis或Zookeeper实现分布式锁时,每次获取或释放锁都需要与这些服务进行交…...
编译原理复习---正则表达式+有穷自动机
适用于电子科技大学编译原理期末考试复习。 1. 正则表达式 正则表达式(Regular Expression,简称regex或regexp)是一种用于描述、匹配和操作文本模式的强大工具。它由一系列字符和特殊符号组成,这些字符和符号定义了一种搜索模式…...
如何使用ChatGPT辅助文献综述,以及如何进行优化?一篇说清楚
目录 1.写在开头 2.ChatGPT 3.提示词研究 4.第一轮研究 5.第二轮研究 6.生成文献综述 嘿宝子们!今天我们要聊的,可是个让学术圈都为之振奋的话题——ChatGPT辅助文献综述。这个教育界的新宠儿,已经不满足于仅仅在学习和教学中露两手了&…...
ZZNUOJ 1601:字母序号(C/C++/Java)
题目描述 我们把字母 A-Z 分别编号为 1-26, 现在给你一个大写字母, 输出这个大写字母的序号。 输入 输入一个大写字母 输出 输出这个大写字母的序号 样例输入 C 样例输出 3 常见的ASCII值 ASCII表中可以记下部分特殊的值(十进制)(字母从A到Z,从a到z,ASCII值依次递增)...
[CISCN 2021初赛]rsa
[CISCN 2021初赛]rsa 源代码: from flag import text,flag import md5 from Crypto.Util.number import long_to_bytes,bytes_to_long,getPrimeassert md5.new(text).hexdigest() flag[6:-1]msg1 text[:xx] msg2 text[xx:yy] msg3 text[yy:]msg1 bytes_to_lo…...
Electron -- Electron Fiddle(一)
Electron Fiddle 是一个由 Electron 团队开发的开源工具,它允许开发者快速创建、运行和调试 Electron 应用。这个工具提供了一个简洁的界面,使用户无需配置复杂的开发环境,就能快速体验和学习 Electron。强烈建议将其安装为学习工具。 学习它…...
java 实现排序的几种方式
冒泡排序(Bubble Sort) 基本原理: 它重复地走访要排序的数列,一次比较两个元素,如果它们的顺序错误就把它们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。 示例代码如下: 登…...
【机器学习与数据挖掘实战】案例06:基于Apriori算法的餐饮企业菜品关联分析
【作者主页】Francek Chen 【专栏介绍】 ⌈ ⌈ ⌈机器学习与数据挖掘实战 ⌋ ⌋ ⌋ 机器学习是人工智能的一个分支,专注于让计算机系统通过数据学习和改进。它利用统计和计算方法,使模型能够从数据中自动提取特征并做出预测或决策。数据挖掘则是从大型数据集中发现模式、关联…...
陀螺仪选型
瑞芬官网 datasheet 陀螺仪、IMU姿态仪、陀螺转角仪、三轴姿态仪、三轴陀螺仪 mid360 imu ICM-40609-D TDK InvenSense | Mouser https://product.tdk.com/system/files/dam/doc/product/sensor/mortion-inertial/imu/data_sheet/ds-000330_icm-40609-d_v1.2.pdf...
【超详细实操内容】django的身份验证系统之限制用户访问的三种方式
目录 1、使用request.user.is_authenticated属性 2、装饰器login_required 3、LoginRequiredMixin类 通常情况下,网站都会对用户限制访问,例如,未登录的用户不可访问用户中心页面。Django框架中使用request.user.isauthenticated属性、装饰器loginrequired和LoginRequire…...
Pika Labs技术浅析(六):自动化技术
Pika Labs 的自动化技术旨在通过工作流引擎和自动化警报系统,帮助用户实现业务流程的自动化和实时监控。 一、自动化技术模块概述 Pika Labs 的自动化技术模块旨在通过以下两个核心组件,实现业务流程的自动化和实时监控: 1.工作流引擎&…...
springboot471基于协同过滤算法商品推荐系统(论文+源码)_kaic
摘 要 传统办法管理信息首先需要花费的时间比较多,其次数据出错率比较高,而且对错误的数据进行更改也比较困难,最后,检索数据费事费力。因此,在计算机上安装协同过滤算法商品推荐系统软件来发挥其高效地信息处理的作用…...
【YashanDB知识库】jdbc查询st_geometry类型的数据时抛出YAS-00101错误
本文内容来自YashanDB官网,原文内容请见 https://www.yashandb.com/newsinfo/7802956.html?templateId1718516 问题现象 某客户的业务在通过YashanDB jdbc驱动查询含有st_geometry列的数据时,报如下异常:YAS-00101 cannot allocate 0 byte…...
ajax中get和post的区别,datatype返回的数据类型有哪些?web开发中数据提交的几种方式,有什么区别。
在 Web 开发中,GET 和 POST 是两种常见的 HTTP 请求方法,它们有一些显著的区别。此外,datatype 参数在 jQuery 的 ajax() 请求中指定了预期的响应数据类型。接下来,我会详细解释这些问题。 1. GET 和 POST 请求的区别 GET 请求 和…...
EKF异常状态自检
https://wenku.csdn.net/column/25p1jkf4vz https://www.zhihu.com/question/293038308/answers/updated https://zhuanlan.zhihu.com/p/12011086094 常用数据分析方法:方差分析及实现!-腾讯云开发者社区-腾讯云 方差分析的七种类型_双因素方差分析 自变…...
《解析 MXNet 的 C++版本在分布式训练中的机遇与挑战》
在深度学习的广袤领域中,分布式训练已成为应对大规模数据和复杂模型训练需求的关键手段。MXNet 作为一款备受瞩目的深度学习框架,其 C版本在分布式训练方面展现出独特的魅力,同时也面临着诸多挑战。深入探究这些优势与挑战,对于推…...
UVM学习总结
问题1:同时出现几个相同的uvm_config_de()哪个有效? UVM中的配置对象是通过uvm_config_db类实现的。uvm_config_db类使用一对名称和值来存储配置信息。当多个uvm_config_db.call()调用同时提供相同名称的配置时,最后一个调用将覆盖之前的调用…...
TCP/IP 介绍:网络通信的基石
TCP/IP 介绍:网络通信的基石 计算机通信协议概述 在数字时代,计算机之间的通信变得至关重要。计算机通信协议(Computer Communication Protocol)是一套规则,定义了计算机如何相互交流信息。这些协议确保了不同制造商…...
华为IPD流程6大阶段370个流程活动详解_第二阶段:计划阶段 — 86个活动
华为IPD流程涵盖了产品从概念到上市的完整过程,各阶段活动明确且相互衔接。在概念启动阶段,产品经理和项目经理分析可行性,PAC评审后成立PDT。概念阶段则包括产品描述、市场定位、投资期望等内容的确定,同时组建PDT核心组并准备项目环境。团队培训涵盖团队建设、流程、业务…...
基于Spring Boot的建材租赁系统
一、系统背景与目的 随着建筑行业的快速发展,建材租赁需求日益增加。传统的建材租赁管理方式大多依赖于纸质文档或简单的电子表格,不仅效率低下,还容易出现信息遗漏和错误。为了解决这些问题,基于Spring Boot的建材租赁系统应运而…...
YOLO v5 Series - MQTT
MQTT...
uni-app开发订单列表页面
目录 一:功能描述 二:功能实现 一:功能描述 订单列表页面包含三个部分,最上面显示订单的状态信息,可以根据订单进行切换,中间显示订单的商品和价格信息,最下面显示订单的操作按钮,可以根据不同的状态操作订单。 二:功能实现 1:状态切换 <view class="nav-…...
14,攻防世界Web_php_unserialize
进入场景 看见代码,解析一下 这段PHP代码定义了一个名为Demo的类,并演示了如何通过URL参数进行反序列化和文件高亮显示的功能,同时也包含了一些安全措施以防止对象注入攻击。下面是对这段代码的逐行解释: 1.<php 开始PHP代码…...
基于单片机的电梯声控系统设计(论文+源码)
1.系统设计 在目前的高楼住宅,商业大厦中电梯是不可或缺的,而传统的电梯控制器系统,通常需要用户用手去按下按键进行控制,但是这种方式在有些情况下,并不完善,比如在本次新冠疫情期间,由于新冠…...
宠物用品电子商务系统|Java|SSM|VUE| 前后端分离
【技术栈】 1⃣️:架构: B/S、MVC 2⃣️:系统环境:Windowsh/Mac 3⃣️:开发环境:IDEA、JDK1.8、Maven、Mysql5.7 4⃣️:技术栈:Java、Mysql、SSM、Mybatis-Plus、VUE、jquery,html 5⃣️数据库可…...
每日一题 341. 扁平化嵌套列表迭代器
341. 扁平化嵌套列表迭代器 展开成数组来解题 class NestedIterator {vector<int> nums;int idx;void flattened(vector<NestedInteger> &nestedList){for(int i0;i<nestedList.size();i){if(nestedList[i].isInteger()){nums.push_back(nestedList[i].get…...
小程序 - 模拟时钟
微信小程序常用API练习 - 模拟时钟小程序开发笔记 模拟时钟 “模拟时钟”微信小程序是一个简约风格的动态时钟,该时钟时间与系统时间一致,且时针、分针、秒针会与系统时间同步更新,用户可以很方便地查看时间。下面将对“模拟时钟”微信小程序…...
UDP的报文结构和特点
1.UDP传输协议的特点 使用UDP传输协议进行通信,过程类似于寄信,它的特点如下: 无连接:知道对端的IP号和端口号就直接进行传输,不需要建立连接;不可靠:没有可靠机制,发送数据包以后&a…...
如何在服务器上克隆、pull、push GitHub私有项目
诸神缄默不语-个人CSDN博文目录 情况是这样的,我直接用git clone命令后,会提示让我输入GitHub账号密码,我输入后它还是显示克隆失败,并显示: Cloning into folder_name... Username for https://github.com: user_na…...
mybatis 动态 SQL
动态 SQL 是 MyBatis 的强大特性之一。如果你使用过 JDBC 或其它类似的框架,你应该能理解根据不同条件拼接 SQL 语句有多痛苦,例如拼接时要确保不能忘记添加必要的空格,还要注意去掉列表最后一个列名的逗号。利用动态 SQL,可以彻底…...
LeetCode 1661. 每台机器的进程平均运行时间
LeetCode 1661. 每台机器的进程平均运行时间 表: Activity ----------------------- | Column Name | Type | ----------------------- | machine_id | int | | process_id | int | | activity_type | enum | | timestamp | float | ----------------------- 该表展示了一家工厂…...
【RabbitMQ】RabbitMQ保证消息不丢失的N种策略的思想总结
文章目录 生产者端(消息发布端)保证机制RabbitMQ服务器端保证机制消费者端(消息接收端)保证机制除了MQ自带的机制,还能做的操作持久化的原理ACK思想 更多相关内容可查看 消息从发送,到消费者接收࿰…...
在21世纪的我用C语言探寻世界本质 ——编译和链接(编译环境和运行环境)
人无完人,持之以恒,方能见真我!!! 共同进步!! 文章目录 一、翻译环境和运行环境二、翻译环境1.编译预处理编译汇编 2.链接 三、运行环境 一、翻译环境和运行环境 在 ANSI C 的任何⼀种实现中&am…...