[翻译] Effective C++, 3rd Edition, Item 19: 视 class design(类设计)为 type design(类型设计)

彻底清理Easy Connect残留:从服务到驱动的完整卸载指南 在企业网络接入场景中,远程客户端常因内核驱动、系统服务和网络过滤组件导致卸载残留,进程无法结束、文件被锁定、注册表项顽固存在。其原理在于驱动挂载网络协议栈,服务守护进程,卸载时资源占用导致清理不彻底。彻底清理的技术价值在于恢复系统纯净、避免网络异常和软件冲突。典型应用场景包括企业办公机、个人笔记本更换或重装客户端。本文针对深信服Easy Connect,提供从停止服务、删除驱动到清理注册表和虚拟网卡的分步操作链路,并给出验证方法和避坑经验。 阅读详情

Item 19: 视 class design(类设计)为 type design(类型设计)

作者:Scott Meyers

译者:fatalerror99 (iTePub's Nirvana)

发布:http://blog.youkuaiyun.com/fatalerror99/

在 C++ 中,就像其它 object-oriented programming languages(面向对象编程语言),通过定义一个新 class(类)来定义一个新 type(类型)。作为一个 C++ 开发者,你的大量时间就这样花费在加大你的 type system(类型系统)上。这意味着你不仅仅是一个 class designer(类设计者),而且是一个 type designer(类型设计者)。重载函数和运算符,控制内存分配和回收,定义 object 的初始化和终结过程——这些全在你的掌控之中。因此你应该在 class design(类设计)中倾注大量心血,就像语言设计者在语言的 built-in types(内建类型)的设计中所倾注的心血。

设计良好的 classes 是具有挑战性的,因为设计良好的 types 是具有挑战性的。良好的 types 拥有简单自然的语法,符合直觉的语义,以及一个或更多高效的实现。在 C++ 中,一个缺乏计划的 class definition(类设计),不可能达到上述任何一个目标。甚至一个 class 的 member functions(成员函数)的执行特征可能受到它们被声明的方式的影响。

那么,如何才能设计高效的 classes 呢?首先,你必须理解你所面对的问题。实际上每一个 class 都需要你面对下面这些问题,其答案通常就导向你的设计的限制因素:

  • 你的新 type(类型)的 objects 应该如何创建和销毁?这些如何做将影响到你的 class 的 constructors(构造函数)和 destructor(析构函数),以及内存分配和回收的函数(operator new,operator new[],operator delete,和 operator delete[] ——参见 Chapter 8)的设计,只要你写了它们。
  • object initialization(对象初始化)和 object assignment(对象赋值)应该有什么不同?这个问题的答案决定了你的 constructors(构造函数)和你的 assignment operators(赋值运算符)的行为和它们之间的不同。这对于不混淆 initialization(初始化)和 assignment(赋值)是很重要的,因为它们相当于不同的函数调用(参见 Item 4)。
  • passed by value(传值)对于你的新 type(类型)的 objects 意味着什么?记住,copy constructor(拷贝构造函数)定义了一个 type(类型)的 pass-by-value(传值)是如何实现的。
  • 你的新 type(类型)的合法值的限定条件是什么?通常,对于一个 class 的 data members(数据成员)来说,仅有某些值的组合是合法的。那些组合决定了你的 class 必须维持的 invariants(不变量)。这些 invariants(不变量)决定了你必须在 member functions(成员函数)内部进行错误检查,特别是你的 constructors(构造函数),assignment operators(赋值运算符),和 "setter" 函数。它可能也会影响你的函数抛出的 exceptions(异常),和你的函数的exception specifications(异常规范)(你用到它的可能性很小)。
  • 你的新 type(类型)是否适合放进一个 inheritance graph(继承图)中?如果你从已经存在的 classes 继承,你将被那些 classes 的设计所约束,特别是它们的函数是 virtual(虚拟)还是 non-virtual(非虚拟)(参见 Items 34 和 36)。如果你希望允许其它 classes 从你的 class 继承,将影响到你声明的函数是否为 virtual(虚拟),特别是你的 destructor(析构函数)(参见 Item 7)。
  • 你的新 type(类型)允许哪种 type conversions(类型转换)?你的 type(类型)身处其它 types(类型)的海洋中,所以是否要在你的 type 和其它 types 之间有一些转换?如果你希望允许 type T1 的 objects implicitly(隐式)转换到 type T2 的 objects,你就要么在 class T1 中写一个 type conversion function(类型转换函数)(例如,operator T2),要么在 class T2 中写一个 non-explicit constructor(非显式构造函数),而且它们都要能够以单一 argument(实参)调用。如果你希望仅仅允许 explicit conversions(显示转换),你就要写执行这个转换的函数,而且你还需要避免使它们的 type conversion operators(类型转换运算符)或 non-explicit constructor(非显式构造函数)能够以一个 argument(实参)调用。(作为一个既是隐式又是显式转换函数的例子,参见 Item 15。)
  • 对于新 type(类型)哪些运算符和函数有意义?这个问题的答案决定你应该为你的 class 声明哪些函数。其中一些是 member functions(成员函数),另一些不是(参见 Items 23,24 和 46)。
  • 哪些标准函数不应该被接受?你需要将那些都声明为 private(私有)的(参见 Item 6)。
  • 你的新 type(类型)中哪些成员可以被访问?这个问题的可以帮助你决定哪些成员是 public(公有)的,哪些是 protected(保护)的,以及哪些是 private(私有)的。它也可以帮助你决定哪些 classes 和/或 functions 应该是 friends(友元),以及一个 class 嵌套在另一个 class 内部是否有意义。
  • 什么是你的新 type(类型)的 "undeclared interface"?出于对 performance(性能),exception safety(异常安全)(参见 Item 29),以及 resource usage(资源使用)(例如,锁和动态内存)的考虑,它提供哪种保证?你在这些领域提供的保证将强行约束你的 classes 的实现。
  • 你的新 type(类型)有多大程度的通用性?也许你并非真的要定义一个新的 type(类型)。也许你要定义一个整个的类型家族。如果是这样,你不需要定义一个新的 class,而是需要定义一个新的 class template(类模板)。
  • 一个新的 type(类型)真的是你所需要的吗?如果你只是要定义一个新的 derived class(派生类),以便让你可以为一个已存在的 class 增加一些功能,也许通过简单地定义一个或更多 non-member functions(非成员函数)或 templates(模板)能更好地达成你的目标。

回答这些问题是困难的,所以定义高效的 classes 是具有挑战性的。然而,如果做好了,在 C++ 中 user-defined classes(用户定义类)生成的 types(类型)至少可以和 built-in types(内建类型)一样好用,它会使一切努力都变的有价值。

Things to Remember

  • class design(类设计)就是 type design(类型设计)。定义一个新 type(类型)之前,确保考虑了本 Item 讨论的所有问题。
RT-DETR改进策略【卷积层】| CGblock 内容引导网络 利用不同层次信息,提高多类别分类能力 (含二次创新) 本文记录的是利用中的模块优化的目标检测网络模型。通过局部特征提取器、周围环境提取器、联合特征提取器和全局环境提取器来提取局部特征、周围环境和全局环境信息,充分利用不同层次的信息。本文将其应用到中,并进行二次创新,使网络能够更好的处理多类别目标的分类能力。CGNet: A Light-Weight Context Guided Network for Semantic Segmentation1️⃣ 首先通过局部特征提取器floc(∗)floc(*)floc(∗)和周围环境提取器fsur(∗)f_{sur } 阅读详情

相关推荐

蓝牙Mesh协议一基本概念

前言 蓝牙SIG联盟在2017年发布了蓝牙Mesh1.0的协议规格,基于低功耗广播包来实现的多对多的通信技术,Mesh协议建立在BLE的物理层和链路层上,所以也可以和BLE的蓝牙进行通信 本章主要介绍蓝牙Mesh的基本概念和协议中的层级结构,也是参考网上的资料,如有异议,欢迎留言指正 基本概念 广播和洪泛 蓝牙Mesh技术是基于BLE的广播报文来实现的,是一种洪泛的消息传输机制,Mesh网络的节点间通过3个广播信道进行通信。当蓝牙Mesh网络中的节点收到消息后会转发这条消息,大大增加了网络的覆盖范围;但

9744

设计class犹如设计type(Treat class design as type design)

强调内容当你定义一个新的class,也就定义了一个新的type,身为C++程序员,你的许多时间主要用来扩张你的类性系统。这意味着你不仅是class设计者,还是type设计者。* 设计高效class首先需要面对的几个问题: 新type的对象应该如何被创建和销毁? 这会影响你的构造和析构函数以及内存分配和释放函数 对象的初始化和对象的赋值该有什么样的差别? 决定你的构造函数和assignm

ON_Foolish的博客 489

CGAL-5.6的安装与编译(Win10+vs2022+CGAL-5.6+Boost1.82.0)

CGAL是Computational Geometry Algorithms Library(计算几何算法库)的缩写,C++的高效算法库。CGAL只是一个头文件库(从5.0版本开始),这意味着CGAL无需编译,只需安装好CGAL的依赖项即可。CGAL5.6。

baidu_34931359的博客 3903

深挖C++:类和对象(中)

(先进后出)

xys_678的博客 254

智能音箱开发者必看:CEVA-BX vs Cadence HiFi音频DSP实战选型指南(附功耗对比表)

本文深入对比了CEVA-BX和Cadence HiFi两大音频DSP架构在智能音箱开发中的性能差异,涵盖语音唤醒、多麦克风阵列处理等核心场景。通过实测数据和功耗对比表,为开发者提供选型参考,帮助优化产品性能和能效表现。

weixin_29309213的博客 227

FID指标实战:如何用Python快速计算生成图像的质量分数(附完整代码)

本文详细介绍了如何使用Python计算Fréchet Inception Distance(FID)指标,以评估生成图像的质量。通过完整的代码示例和优化技巧,帮助开发者快速实现FID计算,并解读分数背后的实际意义,适用于GAN和扩散模型的性能评估。

weixin_28718487的博客 377

C++移动构造函数详解

移动构造函数是C++11引入的一种特殊构造函数,用于从临时对象(右值)"窃取"资源来初始化新对象,而不是进行昂贵的深拷贝。char* data;public:// 移动构造函数:参数是右值引用 &&// 关键:把源对象的资源置空。

拒绝AI文,努力在AI时代写出感动人心的好文章 394

Fabric学习笔记(一)- Centos 7下的Fabric 2.3.2环境搭建

一、 环境准备 (一)、在VMware Workstation 15 安装一个Centos 7的虚拟环境,切换到图形化界面: 参考文章链接:Centos 7切换图形化界面 其中可能在yum groupinstall "X Window System"时会报错:Cannot find a valid baseurl for repo: base/7/x86_6,参考这篇文章即可:安装图形化界面报错解决 (二)、打开终端,安装所需的库: 切换root用户,输入命令:su root yum更新,输入命令:y

茕夜 2611

ThunderKittens 深度解析:一个不基于 MLIR 的 C++ 模板 GPU DSL

Triton 是"让更多人能写 GPU kernel",ThunderKittens 是"让会写的人写得更爽"。前者用 MLIR 换易用性,后者用 C++ 模板换可控性。它们不是替代关系,而是覆盖了 GPU 编程光谱的两端。ThunderKittens 的出现,本质上是对"GPU DSL 必须基于 MLIR"这一默认假设的挑战。编译期类型系统本身就可以是一个强大的 DSL 基础设施,不需要中间 IR,不需要黑盒 pass,也能实现 tile 级抽象和零运行时开销。

Maxwell_Newton的博客 349

2025软考信息安全工程师真题

2025信息安全工程师软考真题

qq_40424393的博客 1708

FPGA实现DDR接口

verilog// DDR2控制器状态机// 初始化序列// 发出初始化命令endendendend// 自动预充电end// 其他状态...endcaseendend。

whm128的博客 1001

跟我学c++中级篇—类型定义的方式

本文系统阐述了编程中类型定义的重要性及c++中的实现方式。重点对比了宏定义、typedef与modern using三种机制,指出using在可读性、灵活性和模板支持上的优势,推荐优先使用。同时提醒开发者注意别名滥用、类型歧义、错误信息冗长等问题,强调统一规范与合理设计。最终结论:在现代c++开发中,应以using为主,兼顾简洁性与可维护性,避免陷入命名混乱与编译困境。

fpcc的专栏 88

【WRF-Urban】使用 LCZ 替换 WRF 运行中的 LUCC 数据

使用 LCZ 替换 WRF 运行中的 LUCC 数据

WW、forever的博客 991

【C++——类和对象(上)】筑基篇:以封装奠定面向对象之基

本文系统梳理C++类与对象的核心知识点,涵盖类的定义、访问限定符(public/private)、类作用域、对象实例化及内存布局。重点解析封装思想、this指针机制、空类大小为1字节的原因,以及类与对象在内存中的存储差异。通过对比C语言结构体与C++类,揭示面向对象设计的优势:数据保护、接口统一、命名隔离与代码可维护性提升。内容由浅入深,适合作为学习笔记与复习参考。

2602_95684935的博客 495

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

C++ 函数模版

模板参数:● template ,T 就是类型占位符,名字可以自定义,习惯用T● 占位符可以在函数返回值、形参、函数内部当作类型使用使用要点模板代码一般写在头文件:编译器需要看到完整模板源码,才能在每个编译单元完成实例化全局函数、类内成员函数都可以写成模板实例化发生在编译阶段,不是运行时隐式实例化:调用时编译器自动推导实参类型,生成对应版本函数。

2501_94041724的博客 307

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

C++ 运行时多态与虚函数机制全面剖析【面试重点】

构成C++ 运行时多态必须是基类的指针或者引用调用虚函数。被调用的函数必须是虚函数,并且派生类必须对该虚函数完成重写/覆盖(Override)。只有基类的指针或引用才能既指向基类对象,又指向派生类对象(切片机制);而只有完成了虚函数重写,派生类与基类才具备不同的函数行为,达到“指向谁就调用谁”的效果。在类成员函数的前面加上virtual关键字修饰,该成员函数就成为了虚函数。public:// 成员函数前加 virtual 修饰,声明为虚函数。

Fuyo_0209的博客 450

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

#SQLite 数据库笔记一:(概念 / 终端指令 / SQL 语句 / C 编程 / 回调函数)

数据库 = 数据的仓库,假设数据是海量。能力说明存储数据持久化保存,程序退出数据还在统计数据、分组、排序数据管理增、删、改、查(CRUD)嵌入式设备上也会用数据库(单片机网关、路由器、工业 HMI 都常见),因为 sqlite 体积小、无需服务进程、单文件即可。数据库 = 库 > 表 > 记录(行) > 字段(列)sqlite3 = 开源、C 写的、单文件、免安装、最多 2T 的嵌入式关系型数据库。

lwq20051110的博客 251

1-10 PostgreSQL中多表连接全解:inner/left/right/full/cross join

本文基于 PostgreSQL 15+ 完整拆解 5 种主流连接:内连接、左连接、右连接、全连接、笛卡尔连接。结合可落地的测试数据,演示每种连接的执行逻辑、返回结果,重点剖析 NULL 值对 JOIN 匹配的核心影响,彻底解决多表连接数据丢失、匹配异常、结果错乱的问题。

zhangjw34的专栏 105

【C++ 基础入门】C++继承(下):问题、底层原理与组合

C++继承(菱形继承的问题、虚继承原理、继承与组合、构造顺序)

2601_96587588的博客 802

蓝桥杯·全国青少年信息素养大赛·电子学会Python/C++考级 备考:莫队算法离线区间查询详解

备赛进行时:第十八届蓝桥杯软件赛报名已于 2026-10-08 10:00 开启、12-18 14:00 截止,省赛定在 2027-04-10(C/C++·Python 程序设计 9:00–13:00);中国电子学会 2026 年 12 月软件编程(C/C++ 一级至十级、Python 一级至六级)考级报名 9/23–12/2 16:00、统考 12-12;全国青少年信息素养大赛 2026—2027 赛季算法应用主题赛也已进入复盘练兵窗口。

IT_Scratch的博客 170

c++ explicit关键字详解

explicit。

拒绝AI文,努力在AI时代写出感动人心的好文章 151

825 mW 顶上 212 °C:ASM491S 的 105 °C/W、250 mA 短路电流与热关断

25 °C 环境里结温 34.1 °C,125 °C 环境里结温 134.1 °C——后者已经离 150 °C 只有 16 °C 了,但还在范围内。换个角度看同一件事:从 25 °C 和从 125 °C 起算,温升都是 86.6 °C,但一个到 111.6 °C(还在范围内),一个到 211.6 °C(远远超限)。这个算例里 20 °C/W 是我假设的,实际值取决于机壳材料、密封程度、有没有风扇,跨度可以从 5 °C/W 到 50 °C/W 以上。外面 50 °C 的机箱,盒内就是 63.9 °C。

ANSILIC的博客 393

《C++ 项目:手写大模型接入 SDK》Gemini接口设计(上):初始化、全量响应实现和测试

本文系统完成了Gemini模型通过OpenAI兼容API的接入开发,基于Apifox验证接口规范,设计并实现GeminiProvider类,涵盖初始化、状态检测、全量响应等核心功能。重点处理了代理配置强制校验、Bearer鉴权、JSON序列化与响应解析等工程细节,并通过GTest与CMake完成单元测试,验证链路可用性。项目遵循策略模式,保持与DeepSeek、ChatGPT等模型的统一抽象接口,显著提升SDK可扩展性。

2501_91275995的博客 398

【容斥原理计数】题解:P9489 ZHY的表示法_容斥原理_计数问题_前缀和问题转化_算法竞赛C++

给定 $ n $ 个正整数,求区间 $[l,r]$ 中有多少正整数 $ x $ 可表示为 $ \sum \lfloor \frac{y}{x_i} \rfloor $。通过二分确定最大 $ y $,转化为求 $ 1 \sim H $ 中是某些 $ x_i $ 倍数的数的个数,利用容斥原理与 DFS 枚举子集计算,结合 LCM 预判剪枝及去重优化,时间复杂度 $ O(2^n \log V) $,可高效处理 $ r \le 10^9 $ 的数据。

YLCHUP的博客 106

头歌 数据结构——C&C++线性表实训

本系列任务围绕线性表的链式实现,依次完成顺序构建、逆序构建、排序插入、查找、删除、求长度及栈、队列、集合等应用。通过动态内存分配与指针操作,掌握单链表的基本操作与实际应用,涵盖插入、删除、遍历、搜索等核心功能,最终实现数据结构在典型场景中的灵活运用。

一名敲代码的苦13程序员 244

字母移动游戏题解:贪心求最长可保留连续子串(附 C 实现)

本题核心思想是:最少移动步数 = 总长度 - 可保留的最长连续子串长度。未移动字母在T中必须为连续子串,在S中需保持相对顺序(即子序列)。通过枚举T的所有连续子串起点,贪心匹配S中的对应字符,求出最长可保留长度L,答案即为n−L。时间复杂度O(n²),空间复杂度O(n),适用于n≤1000。

冻柠茶飞冰走茶 592
上一篇: [翻译] Effective C++, 3rd Edition, Item 18: 使 interfaces(接口)易于正确使用,而难以错误使用
下一篇: [翻译] Effective C++, 3rd Edition, Item 20: 用 pass-by-reference-to-const(传给 const 引用)取代 pass-by-value(传值)(上)
fatalerror99
博客等级 码龄24年 166粉丝 20原创
评论 3
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值