SOLID 原则在 C++ 中:从理论到实践
SOLID 是罗伯特·马丁(Bob 大叔)提出的面向对象编程五大基本原则的首字母缩写。在 C++ 的语境下,这些原则有助于创建灵活、可维护且可测试的代码。在本文中,我们将通过 C++ 的实际示例来剖析每一条原则。
1. Single Responsibility Principle (SRP) — 单一职责原则
核心思想:每个类应该只有一个引起变化的原因。简单来说,一个类只负责一项任务。
反面示例(违反 SRP):
class Report {public: void generateReport() { /* 生成报告 */ } void saveToFile(const std::string& filename) { /* 保存到文件 */ } void printReport() { /* 打印报告 */ }};这里的 Report 类负责生成、保存和打印——三项不同的职责。
正面示例(遵循 SRP):
class Report {public: std::string generate() { /* 生成报告 */ return "report data"; }};
class ReportSaver {public: void save(const std::string& data, const std::string& filename) { // 保存到文件 }};
class ReportPrinter {public: void print(const std::string& data) { // 打印报告 }};现在每个类都有明确的单一职责,这简化了测试和修改。
2. Open-Closed Principle (OCP) — 开闭原则
核心思想:类应该对扩展开放,对修改关闭。你应该能够在不修改现有代码的情况下添加新功能。
反面示例:
enum class ShapeType { Circle, Rectangle };
class Shape {public: ShapeType type;};
class AreaCalculator {public: double calculateArea(const Shape& shape) { if (shape.type == ShapeType::Circle) { // 计算圆的面积 return 3.14 * radius * radius; } else if (shape.type == ShapeType::Rectangle) { // 计算矩形的面积 return width * height; } return 0.0; }};当添加新图形(例如三角形)时,必须修改 AreaCalculator。
正面示例(通过多态实现):
class Shape {public: virtual double area() const = 0; virtual ~Shape() = default;};
class Circle : public Shape { double radius;public: explicit Circle(double r) : radius(r) {} double area() const override { return 3.14159 * radius * radius; }};
class Rectangle : public Shape { double width, height;public: Rectangle(double w, double h) : width(w), height(h) {} double area() const override { return width * height; }};
class AreaCalculator {public: double calculateArea(const Shape& shape) { return shape.area(); }};现在要添加新图形,只需创建一个新的子类,而无需改动 AreaCalculator。
3. Liskov Substitution Principle (LSP) — 里氏替换原则
核心思想:子类的对象应该能够替换基类的对象,而不会破坏程序的正确性。
经典违反示例(矩形-正方形问题):
class Rectangle {protected: int width, height;public: void setWidth(int w) { width = w; } void setHeight(int h) { height = h; } int area() const { return width * height; }};
class Square : public Rectangle {public: void setWidth(int w) override { width = w; height
```