Item18--让接口容易被正确使用,不易被误用

news/2025/12/24 16:31:27/文章来源:https://www.cnblogs.com/belief73/p/19376952

🎯 条款 18:让接口容易被正确使用,不易被误用

(Make interfaces easy to use correctly and hard to use incorrectly)

这是 C++ 接口设计中最重要的指导原则之一。一个好的接口不仅要功能强大、设计精良,更重要的是它要引导用户自然地、正确地使用它,并主动阻止用户犯错

1. 易于正确使用 (Easy to Use Correctly)

设计接口时,应该使用户无需记忆额外的规则或避免某些操作,就能自然而然地正确使用。

示例:std::unique_ptr

std::unique_ptr 在设计上就体现了“易于正确使用”:

  • 自动资源管理: 用户无需手动调用 delete(遵守了条款 13)。
  • 单一所有权: 禁止拷贝构造和拷贝赋值。这意味着用户如果尝试拷贝一个 unique_ptr,编译器会直接报错,从而阻止了“双重释放(double delete)”这类资源所有权转移的常见错误。

2. 不易被误用 (Hard to Use Incorrectly)

这是条款 18 的核心,设计者可以通过多种机制来阻止用户犯下常见的错误。

A. 引入新类型,限制类型转换

问题: 假设我们有一个处理日期的类,用户可能会传入错误的整数来表示月份。

class Date {
public:// 允许用户传入任何 int,可能传入 0 或 13 等非法值Date(int month, int day, int year); 
};

解决方案: 为参数(如月份)创建新的强类型。这样用户只能传入特定的类型对象,而不是随意的整数。

// 引入强类型
struct Month { explicit Month(int m) : val(m) {} int val; };
struct Day { explicit Day(int d) : val(d) {} int val; };
struct Year { explicit Year(int y) : val(y) {} int val; };class Date {
public:// 强制用户传入 Month 对象,而不是 intDate(const Month& m, const Day& d, const Year& y); 
};// 正确使用:
Date d(Month(3), Day(30), Year(2025)); 
// 误用:编译器报错,因为 3 不是 Month 类型
// Date d(3, 30, 2025); 

通过这种方式,我们利用 C++ 的类型系统,把运行时错误(传入非法整数)转化为编译时错误(类型不匹配),从而防止误用。

B. 限制对象的有效性:const

如果某个对象不应该被修改,就应该将其声明为 const。这是最简单、最有效的防止误用方法。

// 确保这个对象在程序执行过程中不会被修改
const SomeClass immutableObject; 

C. 返回智能指针,消除资源泄漏

问题: 接口返回原始指针 (Raw Pointer),用户忘记 delete 导致泄漏(条款 13)。

// 误用:返回原始指针,用户可能忘记 delete
Widget* createWidget(); 

解决方案: 接口返回智能指针(例如 std::unique_ptr),确保资源的自动管理。

// 正确:返回智能指针,资源自动被管理
std::unique_ptr<Widget> createWidget(); 

D. 阻止跨 DLL/SO 边界的内存泄漏

当程序在动态链接库(DLL/SO)之间传递对象时,如果在一个 DLL 中用 new 分配内存,在另一个 DLL 中用 delete 释放,可能会因为使用了不同的堆管理器而导致程序崩溃或泄漏。

解决方案: 确保 DLL 接口只返回智能指针,并且不在接口中暴露原始指针或容易引起问题的内存管理函数。或者提供配套的工厂函数和销毁函数,让内存的分配和释放都发生在同一个模块内。

总结

设计优秀的接口,就是将使用者的错误降到最低。这是通过以下策略实现的:

  1. 一致性: 保持接口行为的一致性(例如,size() 函数对所有容器都返回元素数量)。
  2. 内置防错: 使用类型系统(例如 Month 类型)、const 修饰符、智能指针等,将运行时错误转移到编译期,从而强制用户正确地使用接口。
  3. 封装实现: 隐藏实现细节,只暴露必要的操作,减少用户的选择和出错的可能性。

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

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

相关文章

基于java的SpringBoot/SSM+Vue+uniapp的赛车爱好者交流平台的详细设计和实现(源码+lw+部署文档+讲解等)

文章目录前言详细视频演示具体实现截图技术栈后端框架SpringBoot前端框架Vue持久层框架MyBaitsPlus系统测试系统测试目的系统功能测试系统测试结论为什么选择我代码参考数据库参考源码获取前言 &#x1f31e;博主介绍&#xff1a;✌全网粉丝15W,CSDN特邀作者、211毕业、高级全…

算法日记专题:位运算II( 只出现一次的数字I II III 面试题:消失的两个数字 比特位计数)

&#x1f3ac; 胖咕噜的稞达鸭&#xff1a;个人主页&#x1f525; 个人专栏: 《数据结构》《C初阶高阶》 《Linux系统学习》 《算法日记》⛺️技术的杠杆&#xff0c;撬动整个世界! &#x1f425;位运算常见总结&#xff1a; 本专题的前缀文章&#xff1a; 算法日记专题&#x…

PyTorch - 指南

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

【2025红黑榜】10款常见降AI率工具大汇总(含不限次数免费降AI版本)

&#x1f4a1;写论文最怕什么&#xff1f; 不是查重&#xff0c;而是那句——“AI率过高”。 现在越来越多学校查论文降aigc报告。 我当时AI率高达98%&#xff0c;整个人快崩溃。 为了把那篇论文救回来&#xff0c;我实测了10款热门降ai率工具&#xff0c; 有免费的&#xff0c…

Item25--考虑写出一个不抛异常的 swap 函数

1. 核心现状:默认的 std::swap 够用吗? 绝大多数情况:够用(Rule of Zero) 如果你的类遵循 Rule of Zero(只包含标准库容器、智能指针等成员),你不需要手写 swap。 class ModernWidget {std::string name;std::…

Item25--考虑写出一个不抛异常的 swap 函数

1. 核心现状:默认的 std::swap 够用吗? 绝大多数情况:够用(Rule of Zero) 如果你的类遵循 Rule of Zero(只包含标准库容器、智能指针等成员),你不需要手写 swap。 class ModernWidget {std::string name;std::…

3562. 折扣价交易股票的最大利润

3562. 折扣价交易股票的最大利润 - 力扣(LeetCode) class Solution { public:int maxProfit(int n, vector<int>& present, vector<int>& future, vector<vector<int>>& hierar…

【2025终极测评】10款常见降AI率工具大汇总(含0元免费降AI版本)

&#x1f4a1;写论文最怕什么&#xff1f; 不是查重&#xff0c;而是那句——“AI率过高”。 现在越来越多学校查论文降aigc报告。 我当时AI率高达98%&#xff0c;整个人快崩溃。 为了把那篇论文救回来&#xff0c;我实测了10款热门降ai率工具&#xff0c; 有免费的&#xff0c…

算法日记专题:位运算I(汉明距离I II 面试题:判断是不是唯一的字符 丢失的数字 两个整数相加)

&#x1f3ac; 胖咕噜的稞达鸭&#xff1a;个人主页&#x1f525; 个人专栏: 《数据结构》《C初阶高阶》 《Linux系统学习》 《算法日记》⛺️技术的杠杆&#xff0c;撬动整个世界! &#x1f425;位运算常见总结&#xff1a; 本专题后缀文章&#xff1a; 算法日记专题&#xff…

Item21--必须返回对象时,别妄想返回其 reference

1. 核心矛盾:我们为什么想返回引用? 学习了 Item 20 后,你可能觉得:“传值(pass-by-value)太慢了,有构造和析构的开销。那我干脆把函数的返回值也改成引用吧!” 场景设定 假设你要实现一个有理数类 Rational,…

Item21--必须返回对象时,别妄想返回其 reference

1. 核心矛盾:我们为什么想返回引用? 学习了 Item 20 后,你可能觉得:“传值(pass-by-value)太慢了,有构造和析构的开销。那我干脆把函数的返回值也改成引用吧!” 场景设定 假设你要实现一个有理数类 Rational,…

Item15--在资源管理类中提供对原始资源的访问

🧐 Item 15:在资源管理类中提供对原始资源的访问 这个条款主要讨论的是当您使用一个资源管理类(例如 std::unique_ptr、std::shared_ptr 或您自定义的互斥锁包装器)来持有并管理一个原始资源(如文件描述符、数据…

1985-2024年中国绿色专利数据库(绿色技术专利分类)

企业开展绿色创新研究对实现"双碳"目标和可持续发展具有重要意义。这一举措不仅能帮助企业在环保转型中建立竞争优势&#xff0c;还能通过降低环境成本、开拓新兴市场来增强社会责任表现。作为衡量绿色创新的关键指标&#xff0c;绿色专利数据具有多重价值&#xff1…

Item22--将成员变量声明为 private

1. 语法一致性 (Syntactic Consistency) 这是最浅层的理由,但对使用者体验很重要。如果变量是 public 的:客户端访问时不需要括号,如 obj.length。 如果变量是 private 的(通过函数访问):客户端访问需要括号,如…

Item16--`new` 与 `delete` 的对应规则

👨‍🏫 条款 16 详解:new 与 delete 的对应规则 1. 核心规则回顾分配 (new) 释放 (delete) 语义new T delete p 分配/释放单个对象new T[ ] delete [ ] p 分配/释放对象数组违反这条规则会导致未定义行为 (Undefi…

3777. 使子字符串变交替的最少删除次数

3777. 使子字符串变交替的最少删除次数 #include <iostream> #include <vector> #include <string> #include <algorithm>using namespace std;class Solution { private:// 题目要求创建变量…

预见2026:家居新品首秀平台选择战略——五大核心展会深度评估与推荐 - 匠子网络

基于2025年商业转化数据的权威展会参展决策指南 站在2025年年底的节点回望,大家居行业经历了深度洗牌与创新蝶变。对于计划在2026年推出新品的家居品牌而言,选择正确的展会平台已成为决定市场开局成败的关键战略。基…

研究生必备!8个免费AI论文工具,半天生成5000字问卷论文还有高信度数据

如果你是面临延毕压力、被导师催稿的研究生&#xff0c;或是没钱承担高额知网查重费用、为论文写作绞尽脑汁的大学生&#xff0c;又或是科研任务繁重、时间紧迫的科研人员&#xff0c;那么这篇文章就是为你量身打造的。在学术的道路上&#xff0c;写论文可谓是一座难以翻越的大…

Item17--以独立语句将 `new` 到的对象置入智能指针

💡 条款 17:以独立语句将 new 到的对象置入智能指针 (Store newed objects in smart pointers in standalone statements) 这个条款是关于异常安全 (Exception Safety) 的,它指导我们在初始化智能指针时,应将动…

Item20--宁以 pass-by-reference-to-const 替换 pass-by-value

1. 性能代价:为什么要避免 Pass-by-Value? 在 C++ 中,默认情况下函数参数是按值传递(pass-by-value)的。这意味着当你在函数中传递一个对象时,编译器会调用该对象的拷贝构造函数(Copy Constructor)来制作一个副…