当前位置: 首页 > news >正文

Item19--设计 class 犹如设计 type

🏗️ 条款 19:设计 class 犹如设计 type

(Treat class design as type design)

在 C++ 中,当你创建一个 class(类)时,你实际上是在为这个程序设计一个新的类型(Type)。优秀的类设计必须考虑到与内置类型(如 int, double)同样多的细节,甚至更多。

这个条款提醒我们在设计类时,需要像 C++ 语言的设计者一样,仔细思考所有可能影响用户使用的方面。

1. 考虑对象的创建与销毁 (Creation and Destruction)

你需要决定:

  • 如何创建对象? 考虑构造函数(Constructors)和工厂函数(Factory Functions)。它们应该接受哪些参数?(参考条款 4:注意避免在构造函数中抛出异常。)
  • 如何销毁对象? 考虑析构函数(Destructor)。析构函数需要是虚的 (virtual) 吗?(参考条款 7:为多态基类声明虚析构函数。)

2. 考虑对象的初始化与赋值 (Initialization and Assignment)

你需要决定对象被创建后,能否以及如何被赋值。

  • 赋值行为: 用户可以对你的对象进行赋值吗?如果可以,你需要重载赋值操作符(operator=)。
  • 深拷贝 vs. 浅拷贝: 如果你的类包含指针,是需要执行深拷贝(Deep Copy)来复制指针所指的数据,还是只需要执行浅拷贝(Shallow Copy)?
  • 禁止拷贝: 如果你不希望用户拷贝你的对象(例如,std::unique_ptr),你需要显式地声明这些函数为 delete(参考条款 11:禁止拷贝)。
  • 初始化和赋值的区别: 在构造函数中完成初始化,在赋值操作符中完成赋值,两者行为可能不同。(参考条款 10:让赋值操作符返回一个对 *this 的引用。)

3. 考虑对象的值语义 (Value Semantics)

用户对你的对象执行操作时,它的行为应该像一个内置类型那样自然

  • 合法值: 你的类型有哪些合法值?你需要对构造函数和设置函数进行输入验证,防止对象处于不合法状态。(参考条款 18:让接口容易被正确使用。)
  • 默认值: 你的对象是否有默认状态?如果有,你需要提供默认构造函数。
  • 相等性: 两个对象何时视为相等?你需要考虑重载比较操作符(operator==, operator!= 等)。

4. 考虑对象的类型转换 (Type Conversion)

你需要决定你的类型与其他类型之间如何转换:

  • 隐式转换: 允许你的类型隐式转换为其他类型吗?如果允许,你需要提供隐式转换函数(Conversion Functions)或explicit 的单参数构造函数
    • 注意: 隐式转换常是误用的来源,通常应避免,除非它是接口的必要部分(例如,std::string 允许隐式转换为 C 风格的 const char*)。
  • 显式转换: 如果你需要显式转换,请提供转换成员函数友元非成员函数(例如 static_cast)。

5. 考虑对象的内存分配 (Memory Allocation)

你需要决定是否需要自定义内存管理。

  • 自定义 newdelete 如果你的类有特殊的内存需求(如性能优化、内存池),你可能需要重载 operator newoperator delete。(参考条款 50:小心 operator newoperator delete 的替代品。)
  • 数组形式: 是否需要重载数组形式的 operator new[]operator delete[]?(参考条款 16:成对使用 newdelete 时要采用相同的形式。)

6. 考虑对象的生命周期 (Lifetime Management)

你需要决定谁来管理你的对象的生命周期,这通常涉及到资源管理。

  • RAII: 遵循 RAII(Resource Acquisition Is Initialization)原则,将资源封装在对象中,在构造时获取,在析构时释放。(参考条款 13:以对象管理资源。)
  • 智能指针: 在涉及动态内存和资源时,使用智能指针(std::unique_ptr, std::shared_ptr)来保证对象的自动销毁。

总结要点

方面 对应 C++ 特性/条款 思考要点
构造与析构 构造函数、析构函数 如何创建和销毁?析构函数是否为 virtual
初始化与赋值 拷贝/移动构造、operator= 允许拷贝吗?是深拷贝还是浅拷贝?赋值和初始化有什么区别?
值语义 const、比较操作符 哪些值是合法的?如何比较两个对象是否相等?
类型转换 转换函数、explicit 允许与其他类型隐式/显式转换吗?
内存管理 operator new / operator delete 是否需要自定义内存分配策略?
异常安全 RAII 对象如何处理异常?(参考条款 13, 14, 15)
http://www.jsqmd.com/news/115947/

相关文章:

  • basic_regex
  • c++狼人杀
  • 宠物识别丨基于弱监督学习的宠物视频内容自动标注技术实践 - 指南
  • 朴易天下:道家修行的专业术语分享
  • 个人投资者的落地路径:从“说人话,做量化”到实盘前的三道关
  • 神经网络中的 block 和 module
  • item13--使用对象管理资源
  • 深入解析:蓝桥杯基础算法精讲:模拟与高精度运算实战指南
  • item12-- 拷贝一个对象的所有组成部分
  • sub_match
  • sub_match
  • 抽奖机随机号码生成:3 种算法实现 + 测试全解析(附完整代码)
  • 【零基础精通】Python 字符串全解析:从字符序列到不可变对象的深度构建
  • item14--谨慎考虑资源管理类的拷贝行为
  • python django flask酒店客房管理系统数据可视化分析系统_gq8885n3--论文md5
  • python django flask鹿幸公司员工食堂在线点餐餐饮餐桌预约管理系统的设计与实现_utcnqqs0--论文
  • error_code
  • 虚拟化初步了解
  • Miloco 深度打通 Home Assistant,实现设备级精准控制
  • 好用的大型牛场水滴粉碎机技术强的
  • set_value
  • 日记1217
  • function的类型擦除
  • function bind
  • 日记12,19
  • Item10--令赋值操作符返回一个
  • Item9--绝不在构造和析构过程中调用虚函数
  • python django flask考研互助交流平台_c62p51fu--论文
  • 日记12.18
  • 离散化遍历