SOLID 是面向对象设计的五大通用原则,适用于C++等支持面向对象的语言,旨在提升代码可维护性、可扩展性与低耦合性;其包含单一职责、开闭、里氏替换、接口隔离和依赖倒置原则,强调抽象、组合与契约式设计。

SOLID 不是 C++ 专属的原则,而是面向对象设计(OOD)的五大通用架构原则,由 Robert C. Martin 提出,适用于任何支持面向对象特性的语言(包括 C++)。它不是语法规范,也不是 C++ 标准的一部分,而是一套帮助开发者写出可维护、可扩展、可测试、低耦合、高内聚代码的设计思想。在 C++ 工程中,正确应用 SOLID 能显著降低大型项目重构成本和模块间意外依赖。
单一职责原则(SRP):一个类只做一件事
一个类应该只有一个引起它变化的原因。在 C++ 中,这意味着类的接口(public 成员函数)应围绕同一业务概念组织,避免把“读配置”“解析 JSON”“写日志”全塞进一个 ConfigLoader 类里。否则,改日志格式可能意外破坏配置加载逻辑。
- 判断方法:当你为类增加新功能时,是否需要修改已有成员函数的实现?如果频繁出现,说明职责已扩散
- C++ 实践建议:用命名空间隔离不同关注点;用 PIMPL 模式隐藏实现细节;将 IO、序列化、策略算法拆分为独立类或策略类(如 std::function 或模板参数)
- 反例:
class UserManager { public: void loadFromFile(); void saveToFile(); void validatePassword(); void sendEmail(); };—— 持久化、校验、通知混杂
开闭原则(OCP):对扩展开放,对修改关闭
软件实体(类、模块、函数)应该易于扩展新行为,但无需修改原有代码。C++ 中主要通过抽象(纯虚类)、模板、策略模式、依赖注入来实现。
- 核心手段:定义稳定接口(
class Shape { virtual double area() const = 0; }),让具体形状(Circle、Rect)继承并实现,新增 Triangle 无需改动计算总面积的函数 - C++ 特色支持:模板可零成本抽象(
template),std::variant + std::visit 支持类型安全的扩展分支void process(const T& obj) - 注意陷阱:过度抽象会增加复杂度;优先用组合+接口代替继承深链;避免“为未来可能的需求提前扩展”
Liskov 替换原则(LSP):子类型必须能替换父类型
所有使用基类指针/引用的地方,换成其任意派生类对象后,程序行为不变且不抛出意外异常。这是继承关系的语义契约,不是语法允许就行。
立即学习“C++免费学习笔记(深入)”;
- C++ 中常见违反:派生类重写虚函数时加强前置条件(如要求参数 > 0,而基类允许 0)、削弱后置条件(返回空指针而非约定非空)、改变异常规格(基类 noexcept,子类 throw)、修改可变性(基类 const 成员函数,子类内部修改 mutable 成员破坏逻辑不变性)
- 验证方式:若基类有文档契约(如“add() 总是使 size() 增加 1”),每个派生类都必须满足
- 替代方案:当继承难以满足 LSP,优先用组合(Has-a)或类型擦除(如 std::any / 自定义 type-erased wrapper)
接口隔离原则(ISP):客户不应依赖它不需要的接口
不要强迫客户端依赖庞大臃肿的接口。C++ 中应避免“上帝接口”,而按调用方角色拆分成小而专注的抽象类。
- 典型问题:
class IWorker { virtual void work() = 0; virtual void eat() = 0; virtual void sleep() = 0; }—— 机器人实现 eat/sleep 无意义,却必须提供空实现 - C++ 推荐做法:定义多个窄接口,如
IWorkable、IFeedable,让 Human 继承两者,Robot 只继承IWorkable - 结合现代 C++:用 concept 约束模板参数(
template),比运行时虚函数更轻量且编译期检查requires Workable void startShift(T& w);
依赖倒置原则(DIP):依赖抽象,不依赖具体
高层模块(业务逻辑)不应依赖低层模块(数据库、网络),二者都应依赖抽象(接口)。抽象不应依赖细节,细节应依赖抽象。
- C++ 实现关键:用指针/引用持有抽象基类(
std::unique_ptr),通过构造函数或 setter 注入,而非在类内部 new 具体类型 - 避免硬编码依赖:
class OrderService { Database db_; };→ 违反 DIP;应改为class OrderService { std::unique_ptrstorage_; }; - 辅助机制:结合工厂模式(
StorageFactory::create("redis"))或依赖注入框架(如 Boost.DI)管理生命周期,但 C++ 更推荐手动控制以保持清晰性
掌握 SOLID 不是为了死守教条,而是培养对模块边界、变化根源和抽象粒度的敏感度。在 C++ 项目中,它常与 RAII、移动语义、constexpr 等特性协同,共同支撑稳健的系统架构。不复杂但容易忽略。











