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

【读书笔记】《C++ Software Design》第二章:The Art of Building Abstractions

《C++ Software Design》第二章:The Art of Building Abstractions

本章详细探讨如何在 C++ 中构建高质量的抽象,包括行为预期、一致性、所有权管理和文档化。

Guideline 6: Adhere to the Expected Behavior of Abstractions

6.1 An Example of Violating Expectations

  • 示例场景:实现一个 Stack<T> 类时,提供 pop() 方法返回 T&,但在空栈调用时未抛出异常,而是返回未定义引用。

  • 问题:客户端无法预期 pop() 行为,违反直觉。

  • 解决方案

    • 改用 std::optional<T> 返回值,或抛出明确异常 std::underflow_error
    • 添加文档注释,明确表明函数的异常保证级别(noexcept 语义)。

6.2 The Liskov Substitution Principle

  • 定义:子类型必须能够替换父类型且不改变程序语义。

  • 具体实践

    • 前置条件:子类方法不应要求更严格输入。

    • 后置条件:子类方法输出应满足基类声明的约定。

    • 示例

      struct IShape { virtual double area() const = 0; };
      struct Rectangle : IShape { double area() const override; };
      struct Square : Rectangle { double side; double area() const override { return side * side; } };
      
    • 确保 Square 中不破坏 Rectangle 的预期行为,如修改 side 时边长一致性。

6.3 Criticism of the Liskov Substitution Principle

  • 争议:严格遵循 LSP 可能导致复杂的类型层次和过度抽象。
  • 作者观点:注重抽象的语义契约即可,不必机械化实施所有 LSP 条件。
  • 实践建议:编写契约测试(Contract Tests)验证继承层次的行为一致性。

6.4 The Need for Good and Meaningful Abstractions

  • 要点:抽象应贴合领域概念,避免陷入技术细节。

  • 示例:定义 Money 类型:

    class Money {long cents;
    public:explicit Money(long c): cents(c) {}double as_dollars() const { return cents / 100.0; }
    };
    
  • 好处:减少单元转换错误,增强类型安全性与可读性。

Guideline 7: Understand the Similarities Between Base Classes and Concepts

  • 继承与概念:两者均定义范畴与行为规范。

  • 运行时 vs 编译时:继承多态在运行时决议;概念约束在编译时检查。

  • 示例对比

    // 继承多态
    struct IFoo { virtual void foo() = 0; };
    void callFoo(IFoo* f) { f->foo(); }// 概念约束
    template<typename T>
    concept Fooable = requires(T a) { a.foo(); };
    void callFoo(Fooable auto& f) { f.foo(); }
    
  • 实践:对性能敏感场景优先使用概念,需动态扩展场景使用继承。

Guideline 8: Understand the Semantic Requirements of Overload Sets

8.1 The Power of Free Functions: A Compile-Time Abstraction Mechanism

  • 优势:支持对第三方类型扩展接口,无需修改原始类。

  • 示例

    struct Vector2D { float x, y; };
    inline float length(const Vector2D& v) { return std::hypot(v.x, v.y); }
    

8.2 The Problem of Free Functions: Expectations on the Behavior

  • 契约:自由函数应与成员函数语义一致。

  • 示例std::data(), std::size() 应返回与成员函数相同结果。

  • 实践

    • 在头文件中使用 using std::data; 保证 ADL 正常。
    • 文档明确输出和异常语义。

Guideline 9: Pay Attention to the Ownership of Abstractions

9.1 The Dependency Inversion Principle

  • 实践示例

    struct ILogger { virtual void log(std::string_view) = 0; };
    class ConsoleLogger : public ILogger { void log(std::string_view msg) override { std::cout<<msg; } };
    class App { std::unique_ptr<ILogger> logger; };
    

9.2 Dependency Inversion in a Plug-In Architecture

  • 步骤

    1. 定义插件接口 IPlugin
    2. 插件库导出 createPlugin() C 接口。
    3. 主程序用 dlopen/dlsym 加载并注册。
  • 代码

    extern "C" IPlugin* createPlugin();
    

9.3 Dependency Inversion via Templates

  • 示例

    template<typename Logger>
    class App { Logger logger; };
    

9.4 Dependency Inversion via Overload Sets

  • 示例

    void save(Data& d) { d.save(); }  // 自由函数调用 d.save()
    

9.5 DIP vs SRP

  • DIP:管理高低层依赖。
  • SRP:管理类职责。
  • 结合:通过细粒度接口同时满足二者。

Guideline 10: Consider Creating an Architectural Document

  • 目的:提升团队对系统全貌的理解。

  • 建议文档

    • 组件图(Component Diagram)
    • 类图(Class/Concept Diagram)
    • 序列图(Sequence Diagram)
    • 数据流图(Data Flow Diagram)
  • 工具:PlantUML、Mermaid。

  • 实践:将 UML 源文件纳入版本控制,与代码同步迭代。

http://www.dtcms.com/a/276238.html

相关文章:

  • Ruby如何采集直播数据源地址
  • OpenEuler操作系统中检测插入的USB设备并自动挂载
  • 【数据结构】反射、枚举 和 lambda表达式
  • Golang 面向对象(封装、继承、多态)
  • 【C语言】指针进阶:指针和数组
  • 手把手教你用YOLOv10打造智能垃圾检测系统
  • 第七章应用题
  • Geant4 安装---Ubuntu
  • 一篇博客学习Lua_安装使用+语法详解
  • Lua ADB 接口文档
  • RMSNorm实现
  • 2.单例模式
  • Vim的magic模式
  • blender uv小技巧
  • Python 包管理新时代:深入了解 `uv` 的使用与实践
  • OpenVela之模拟器调试
  • 【kubernetes】--Controller(StatefulSet)
  • 【PTA数据结构 | C语言版】链式队列的3个操作
  • Git常用命令一览
  • pyqt5界面开发学习
  • 034_多态的实现(编译时 / 运行时)
  • 洛谷 P11961 [GESP202503 五级] 原根判断-提高+/省选-
  • Vue工程化
  • Spring Boot 基础入门与实战:从框架理解到项目搭建
  • 如何检测自动化设备中的直线导轨品质是否优良?
  • Oracle 数据库实战项目
  • SAC : 具有随机Actor的离策略最大熵深度强化学习
  • Android开发中RxJava的使用与原理
  • 杨娇兽の阴谋
  • 基于springboot+Vue的二手物品交易的设计与实现