逻辑设计问题 -- 设计一个函数
文章目录
- 设计一个函数
- 函数接口规格说明
- 运算符或者非运算符
- 自由或成员运算符
- 虚函数或非虚函数
- 纯虚函数或者非纯虚函数
- 静态或者非静态成员函数
- const 成员函数或者非const成员函数
- 公共的、保护的或者私有的成员函数
- 通过值、引用或者指针返回
- 返回const 或者非const
- 可选参数或者必要参数
- 通过值、引用还是指针来传递参数
- 将参数作为const还是非const传递
- 友元或非友元函数
- 内联或非内联函数
- 在接口中使用基本类型
- 在接口中使用short
- 在接口中使用unsigned
- 在接口中使用long
- 在接口中使用float、double和long double
- 特殊情况函数
- 转换运算符
- 编译器产生的值语义
- 析构函数
- 小结
设计一个函数
函数接口规格说明
在确定C++函数接口时,有下列问题需要研究:
- 运算符或者非运算符函数
- 自由或者成员运算符
- 虚函数或者非虚函数
- 纯虚成员函数或非纯虚成员函数
- 静态或非静态成员函数
- const或非const成员函数
- 公共的、保护的还是私有的成员函数
- 通过值、引用还是指针返回
- 返回const还是非const
- 参数是可选的还是必需的
- 通过值、引用还是指针传递参数
- 将参数作为const还是非const传递
有两个组织问题,虽然不是逻辑接口的一部分但是也必须考虑:
- 友元或者非友元函数
- 内联或者非内联函数
运算符或者非运算符
可读性应该是使用运算符重载的主要原因
一个重载运算符的语义对客户应该是自然的、明显的和直观的
用户自定义类型的重载运算符的语法属性,应该反应已经为基本类型定义了的属性
让用户自定义运算符的语法术语模仿预先确定的C++运算符,以避免意外并使他们的使用更可以预知
自由或成员运算符
C++语言本身可作为用户自定义运算符模仿的一个客观和适宜的标准
重载运算符中的不一致问题,对客户来说可能是明显的,讨厌的和高代价的
虚函数或非虚函数
不必为了获得多态行为而损害语法问题,例如双目运算符的对称隐式转换
虚函数实现行为上的变化;数据成员实现值的变化
隐藏:一个成员函数若在与一个基类或文件作用域中声明的某个函数同名,则隐藏基类中的函数
重载:一个函数用定义在同一个作用域的同样的名称重载了另一个函数的名称覆盖:一个成员函数覆盖了在一个基类中声明的虚拟的同样的函数
重新定义:一个函数的默认定义被另一个定义不可挽回的取代
避免将一个基类函数隐藏在一个派生类中
纯虚函数或者非纯虚函数
静态或者非静态成员函数
静态成员函数通常用于实现一个单独的工具类中的非基本功能
const 成员函数或者非const成员函数
如果一个函数只有一个单一参数,该参数是指向某个对象的引用,并且若不经过显式的转换就不能从函数体 内部获得一个指向同一个对象的非const引用,那么这个对象是const正确的
系统中的每一个对象都应该是const正确的
从一个const成员函数返回一个非const对象可能会破坏一个系统的const正确性
在一个系统中,如果一个只有一个参数的函数未通过显式转换就不能获得一个指向这些对象中的任何一个的可写引用,那么这个系统就是const正确的
一个系统应该是const正确的
如果一个系统的转换图未包含同时涉及任何一个类型的const和非const版本的循环,那么这个系统就是const正确的
在抛弃const的时候至少考虑2次
公共的、保护的或者私有的成员函数
如果成员函数不是公共的,那么会使普通用户也要接触为绝缘的实现细节
所有的虚函数和保护函数都是派生类作者考虑的事项
通过值、引用或者指针返回
对于返回一个错误状态来说,整数值0应该总是意味着成功
通常函数成功工作只有一种方式,而它失败却有若干种方式;作为客户,我们可以不关心它为什么失败
通过加载一个可修改的句柄参数返回一个动态分配对象,比通过非const指针返回那个对象更不容易产生内存泄漏
回答是或者否的函数应该被适当命名(如isValid),并且返回一个不是0就是1的值
返回const 或者非const
避免将结果(从函数通过值返回的)声明为const
可选参数或者必要参数
默认参数可以是函数重载的一种有效替代品,尤其是在不涉及绝缘的地方
避免那些需要一个未命名的临时对象的结构的默认参数
通过值、引用还是指针来传递参数
千万不要通过值传递一个用户自定义类型个一个函数
通过参数返回值要保持一致(例如,避免声明非const引用参数)
避免将一个函数的任何参数的地址存储在函数结束后仍会保留的位置;改为传递该参数的地址。
永远不要企图删除一个通过引用传递的对象
将参数作为const还是非const传递
如果无论何时一个形参通过引用或者指针传递其实参给一个函数,该函数都既不修改这个实参也不存储它的可写地址,那么这个形参就应该声明为const
避免将通过值传递给一个函数的形参声明为const
考虑将那些会激活可修改访问的形参(也许除了那些有默认实参的形参)放在那些通过值、const引用或const指针来传递实参的形参之前。
友元或非友元函数
避免不必要的友元关系可以提高可维护性
避免给单独的函数授予友元关系
内联或非内联函数
如果函数体内产生的对象的代码大于同样的非内联函数调用本身所产生的对象代码,那么应该避免将该函数声明为inline
若你的编译器不会产生内联函数,那么应该避免将一个函数声明为inline
在接口中使用基本类型
在接口中使用short
避免在接口中使用short,改为使用int。
在代码中直接明确地说明设计决策(而不是依赖于注释)是一个设计目标;设计能安全使用和容易维护的健壮性接口偶尔会与这个目标形成竞争关系
在接口中使用unsigned
避免在接口中使用unsigned整数,改为使用int
有时候注释比直接在代码中表达一个接口决策要更好
在接口中使用long
在接口中避免使用long ;改为assert(sizeof(int)>=4),并使用int或者一个用户自定义的大整数类型
在接口中使用float、double和long double
考虑在接口中对于浮点类型只使用double,除非有强制性的原因才使用float或者long double
在实际出现的大多数情况下,为了在接口中能表达整数和浮点数,所需要的唯一基本类型就是int和double
特殊情况函数
转换运算符
隐式转换会影响类型安全,会引入二义性,并且一般来说会增加维护程序的开销
会激活隐式转换的构造函数,尤其是从广泛使用的类型或者基本类型的转换,会破坏由强类型所提供的安全性
考虑避免cast运算符,尤其是对基本整数类型,改为进行显式的转换
编译器产生的值语义
为任何定义在头文件中的类显式的声明构造函数和赋值运算符,甚至在默认的实现是充分的情况下
析构函数
在每一个声明了一个虚函数的类中,把析构函数显式地声明为类中的第一个虚函数,并且非内联的定义
在没有另外声明虚函数的类中,显式地把析构函数声明为非虚拟的并且适当地对它进行定义(内联的或者非内联的)
小结
C++语言在描述函数级接口方面提供了大量的灵活性。当我们设计每个函数时,我们必须至少研究14个独立的维妮塔。每个都决定都会引起必须在上下文中解决的额外考虑:
- 运算符或者非运算符函数
- 自由运算符或者成员运算符
- 虚函数或者非虚函数
- 纯虚成员函数或者非纯虚成员函数
- 静态或者非静态成员函数
- const或者非const成员函数
- 公共的保护的或者私有的成员函数
- 通过值、引用或者指针返回
- 返回const或者非const
- 实参是可选的还是必须的
- 通过值、引用或者指针传递实参
- 将实参作为const或者非const传递
- 友元或者非友元函数
- 内联或者非内联函数
在函数的接口中有许多可选择的整数类型可供使用:short、unsigned、long等。在实际中一个32位机器上,在接口中我们需要的唯一整数类型是int,任何使用其他类型都潜在的存在效率低,不能封装、易于出错或者只是使用起来很麻烦的可能性
在C++中有三种可能选择浮点类型:float、double以及long double。在C中,在将浮点数作为参数传递之前,传统上将所有的浮点参数都转换成double。大多数硬件都适用于尽可能有效地处理double值。所有的浮点数都应该在接口中被表达为double,除非有强制原因要求不这么做
转换运算符与编译时类型安全是相互竞争的关系。接受单个参数的构造函数会激活隐式转换。但是这样的结构是许多接口的必要的一个部分。另一方面,转换运算符是容易避免的,只要提供显式的转换函数即可。有时候通过隐式转换可以增强可用性。但是在大多情况下,隐式转换是一种倾向,尤其是当他包含一个基本整数类型时。
C++编译器会自动产生一些未定义的函数。不依赖默认行为有很多原因,尤其是当接口在整个系统中被广泛使用时。许多C++实现依赖至少有一个非内联函数定义的虚函数。在我们的风格中,这个虚函数总是析构函数。一些当前流行的编译器不允许显式地调用没有显式声明的析构函数。在实践中,显式地定义每个函数的析构函数都是明智的。对于没有虚函数的类来说,内联地定义还是非内联的定义析构函数都是合适的。对于有虚函数的类来说,应该非内联地定义析构函数。对于协议类,析构函数应该为空。
相关文章:

逻辑设计问题 -- 设计一个函数
文章目录 设计一个函数函数接口规格说明运算符或者非运算符自由或成员运算符虚函数或非虚函数纯虚函数或者非纯虚函数静态或者非静态成员函数const 成员函数或者非const成员函数公共的、保护的或者私有的成员函数通过值、引用或者指针返回返回const 或者非const可选参数或者必要…...

RHCE 补充:判断服务状态
内容补充:判断服务状态 systemctl 命令 系统控制管理命令工具 常用指令 1、启动 systemctl start 程序名 若要启动多个程序名,使用空格隔开,下同 2、重启:类似主机先断电再启动的一个状态 systemctl restart 程序名 3、停…...

计算机网络:物理层 - 编码与调制
计算机网络:物理层 - 编码与调制 基本概念编码不归零制编码归零制编码曼彻斯特编码差分曼彻斯特编码 调制调幅调频调相混合调制 基本概念 在计算机网络中,计算机需要处理和传输用户的文字、图片、音频和视频,他们可以统称为消息数据…...

《量子计算:揭开未来科技新篇章》
随着科技的不断发展,量子计算作为一项颠覆性的技术逐渐走进人们的视野,引发了广泛的关注和探讨。本文将围绕量子计算的技术进展、技术原理、行业应用案例、未来趋势预测以及学习路线等方向,深入探讨这一领域的前沿动态和未来发展趋势。 量子…...

机器人机械手加装SycoTec 4060 ER-S电主轴高精密铣削加工
随着科技的不断发展,机器人技术正逐渐渗透到各个领域,展现出前所未有的潜力和应用价值。作为机器人技术的核心组成部分之一,机器人机械手以其高精度、高效率和高稳定性的优势,在机械加工、装配、检测等领域中发挥着举足轻重的作用…...

docker 共享内存不足问题
在启动容器时增加共享内存大小: 您可以通过在docker run命令中添加--shm-size参数来指定更大的共享内存大小。例如,如果您需要32GB的共享内存,可以这样做: docker run --shm-size32g -it your-docker-image 这里的your-docker-im…...

英语口语 3.27
keep It straight :竖着放 turn it to the side:横过来放 i get my shit done:shit(everything)任何事情 我都会去做的 that‘s what’s up 可以的可以的 thats cool zodiac sign :生肖 座 i sense that :我感受到了 talent”艺人 influencer:有影响力的人 …...

pytest之统一接口请求封装
pytest之统一接口请求封装 pytest的requests_util.pyrequests_util.py 接口自动化测试框架的封装yaml文件如何实现接口关联封装yaml文件如何实现动态参数的处理yaml文件如何实现文件上传有参数化时候,怎么实现断言yaml的数据量大怎么处理接口自动化框架的扩展&#…...

使用npm仓库的优先级以及.npmrc配置文件的使用
使用npm仓库的优先级以及.npmrc配置文件的使用 概念如何设置 registry(包管理仓库)1. 设置项目配置文件2. 设置用户配置文件3. 设置全局配置文件4. .npmrc文件可以配置的常见选项 概念 npm(Node Package Manager)是一个Node.js的…...

Netty源码剖析——ChannelHandlerContext 篇(三十七)
ChannelHandlerContext 作用及设计 ChannelHandlerContext 继承了出站方法调用接口和入站方法调用接口 ChannelOutboundInvoker 和 ChannelInboundInvoker 部分源码 这两个invoker就是针对入站或出站方法来的,就是在入站或出站 handler 的外层再包装一层,…...

5.92 BCC工具之bitesize.py解读
一,工具简介 bitesize工具按进程名称显示请求块大小的I/O分布。 它通过监视磁盘上的读取和写入操作,记录每个操作的大小。再将跟踪到的 I/O 操作按照大小分组,通常是以 2 的幂次方(如 4K、8K、16K 等)进行划分,并统计每个大小范围内的 I/O 操作数量。 二,代码示例 #…...

jupyter notebook导出含中文的pdf(LaTex安装和Pandoc、MiKTex安装)
用jupyter notebook导出pdf时,因为报错信息,需要用到Tex nbconvert failed: xelatex not found on PATH, if you have not installed xelatex you may need to do so. Find further instructions at https://nbconvert.readthedocs.io/en/latest/install…...

压力测试(QPS)及测试工具Locust
压力测试: 通常指的是确定接口或服务能够处理的最大请求量(吞吐量)和并发用户数,同时保持合理的响应时间和稳定性。 性能目标 最大吞吐量:系统每秒可以处理的请求数。最大并发用户数:系统可以同时支持的…...

canal: 连接kafka (docker)
一、确保mysql binlog开启并使用ROW作为日志格式 docker 启动mysql 5.7配置文件 my.cnf [mysqld] log-binmysql-bin # 开启 binlog binlog-formatROW # 选择 ROW 模式 server-id1一定要确保上述两个值一个为ROW,一个为ON 二、下载canal的run.sh https://github.c…...

45 对接海康视频九宫格的实现
前言 这里主要是 来看一下 海康视频 的一个九宫格播放的需求 然后 在实际使用的过程中产生了一些问题, 比如 增加一个视频, 应该只增量请求这一个视频的服务, 而一些实现下是全量请求了 整个视频列表的服务 另外 就是全屏播放, 如果是 自己写样式来实现 全屏播放, 可能需要 …...

二-容量管理之容量水位
容量水位概念 容量水位(Capacity Level)是指一个系统或服务所使用资源的程度、范围和可承受能力,通常以百分比表示。在容量管理中,容量水位是非常重要的指标,用于衡量系统或服务的健康状况、资源利用率以及未来容量需求。 容量水位通常是根据一些关键指标进行计算,例如…...

计算机网络——数据链路层(差错控制)
计算机网络——数据链路层(差错控制) 差错从何而来数据链路层的差错控制检错编码奇偶校验码循环冗余校验(CRC)FCS 纠错编码海明码海明距离纠错流程确定校验码的位数r确定校验码和数据位置 求出校验码的值检错并纠错 我们今年天来继…...

【搜索引擎1】Ubuntu通过deb方式安装ElasticSearch和Kibana、ik中文分词插件
1、官网下载文件 版本为官网最新版本,ElasticSearch与Kibana版本必须保持一致 ElasticSearch下载地址:Download Elasticsearch | Elastic Kibana下载地址:Past Releases of Elastic Stack Software | Elastic 下载选择DEB文件 ik插件下载…...

1.0 html(1)
html 一、基本介绍 1、定义:html是一种超文本标记语言,也是一种标识性语言(不是编程语言) 标记:记号(绰号) 超文本:就是页面内容可以包含图片、链接,音乐,…...

基于SpringBoot和Leaflet的行政区划地图掩膜效果实战
目录 前言 一、掩膜小知识 1、GIS掩膜的实现原理 2、图层掩膜流程 二、使用插件 1、leaflet-mask介绍 2、核心代码解释 三、完整实例实现 1、后台逻辑实现 2、省级行政区划查询实现 3、行政区划定位及掩膜实现 4、成果展示 总结 前言 在之前的博客提过按空间矢量…...

【机器学习之---数学】马尔科夫链
every blog every motto: You can do more than you think. https://blog.csdn.net/weixin_39190382?typeblog 0. 前言 马尔科夫 1. 概念 1.1 引言 马尔可夫链在许多领域都有应用,包括物理学、生物学、工程学、经济学和计算机科学等。在计算机科学中࿰…...

教程3_图像的轮廓
目录 目标 1. 特征矩 2、轮廓质心 3. 轮廓面积 4. 轮廓周长 5. 轮廓近似 6. 轮廓凸包 7. 边界矩形 7.1.直角矩形 7.2. 旋转矩形 8. 最小闭合圈 9. 拟合一个椭圆 10. 拟合直线 目标 在本文中,我们将学习 - 如何找到轮廓的不同特征,例如面积&…...

【Linux】-Linux下的编辑器Vim的模式命令大全及其自主配置方法
目录 1.简单了解vim 2.vim的模式 2.1命令模式 2.2插入模式 2.3底行模式 3.vim各模式下的命令集 3.1正常(命令模式下) 3.1.1光标定位命令 3.1.2 复制粘贴 3.1.3 删除 3.1.4 撤销 3.1.5大小写转换 3.1.6替换 「R」:替换光标所到之处的字符&…...

基于SpringBoot和Vue的车辆管理系统的设计与实现
今天要和大家聊的是一款基于SpringBoot和Vue的车辆管理系统的设计与实现 !!! 有需要的小伙伴可以通过文章末尾名片咨询我哦!!! 💕💕作者:李同学 💕…...

R折线图(自备)
目录 折线图基础 创建散点和折线图 复杂折现加图例 折线图柱状图 数据处理 进行差异检验 基础绘图折线 基础绘图箱线 进行合并 双轴柱状与折线图 数据 折线图基础 创建散点和折线图 rm(list ls()) opar <-par(no.readonlyTRUE)##自带orange数据集 par(mfrowc…...

web学习笔记(四十五)Node.js
目录 1. Node.js 1.1 什么是Node.js 1.2 为什么要学node.js 1.3 node.js的使用场景 1.4 Node.js 环境的安装 1.5 如何查看自己安装的node.js的版本 1.6 常用终端命令 2. fs 文件系统模块 2.1引入fs核心模块 2.2 读取指定文件的内容 2.3 向文件写入指定内容 2.4 创…...

基于Gabor滤波器的指纹图像识别,Matlab实现
博主简介: 专注、专一于Matlab图像处理学习、交流,matlab图像代码代做/项目合作可以联系(QQ:3249726188) 个人主页:Matlab_ImagePro-CSDN博客 原则:代码均由本人编写完成,非中介,提供…...

55、Qt/事件机制相关学习20240326
一、代码实现设置闹钟,到时间后语音提醒用户。示意图如下: 代码: #include "widget.h" #include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget), speecher(new QTextToSpeech(t…...

Clip Converter - 视频在线下载方法
Clip Converter - 视频在线下载方法 1. Video URL to Download2. Continue3. StartReferences YT to MP4 & MP3 Converter! https://www.clipconverter.cc/ Clip Converter is a free online media conversion application, which allows you to reocord, convert and do…...

【No.19】蓝桥杯简单数论上|模运算|快速幂|GCD|LCM|刷题统计|RSA解密|核桃的数量(C++)
简单数论 模运算 定义:模运算为 a 除以 m 的余数,记为 a mod m,有 a mod m a % m模运算是大数运算中的常用操作。如果一个数太大,无法直接输出,或者不需要直接输出,可以把它取模后,缩小数值再…...