C++ 开闭原则

C++中的开闭原则(Open-Closed Principle, OCP)是面向对象设计的核心原则之一,其核心思想是:软件实体(类、模块、函数等)应对扩展开放,对修改关闭。这意味着当需求变化时,应通过新增代码(如新增类或方法)来扩展功能,而非直接修改现有代码,从而降低维护成本并提高系统稳定性。

代码示例:通过抽象基类实现开闭原则

以下是一个计算器程序的改进案例,展示了如何从违反开闭原则的设计改进为符合原则的设计。

1. 违反开闭原则的原始设计

原始计算器类直接通过条件判断处理不同运算,新增运算需修改getResult方法,违反开闭原则。

#include <iostream>
#include <string>
using namespace std;

class Calculator {
public:
    Calculator(int a, int b, string op) : a(a), b(b), op(op) {}

    int getResult() {
        if (op == "+") return a + b;
        else if (op == "-") return a - b;
        else if (op == "*") return a * b;
        else if (op == "/") return a / b;
        // 新增运算(如取模%)需修改此方法,违反OCP
        return 0;
    }

private:
    int a, b;
    string op;
};

int main() {
    Calculator calc(10, 5, "+");
    cout << "Result: " << calc.getResult() << endl; // 输出15
    return 0;
}

问题:新增运算(如取模%)需直接修改getResult方法,可能引入错误,且需重新测试所有分支。

2. 符合开闭原则的改进设计

通过抽象基类Operation定义运算接口,具体运算由派生类实现。新增运算时,仅需新增派生类,无需修改现有代码。

#include <iostream>
#include <memory> // 使用智能指针管理动态内存
using namespace std;

// 抽象基类:定义运算接口
class Operation {
public:
    virtual int calculate(int a, int b) = 0;
    virtual ~Operation() = default; // 虚析构函数确保派生类对象被正确销毁
};

// 具体运算类:加法
class AddOperation : public Operation {
public:
    int calculate(int a, int b) override { return a + b; }
};

// 具体运算类:减法
class SubtractOperation : public Operation {
public:
    int calculate(int a, int b) override { return a - b; }
};

// 具体运算类:乘法(新增运算示例)
class MultiplyOperation : public Operation {
public:
    int calculate(int a, int b) override { return a * b; }
};

// 计算器类:通过接口调用具体运算
class Calculator {
public:
    Calculator(unique_ptr<Operation> op) : op(move(op)) {}

    int getResult(int a, int b) {
        return op->calculate(a, b);
    }

private:
    unique_ptr<Operation> op; // 使用智能指针管理运算对象
};

int main() {
    // 测试加法
    Calculator addCalc(make_unique<AddOperation>());
    cout << "Addition: " << addCalc.getResult(10, 5) << endl; // 输出15

    // 测试减法
    Calculator subCalc(make_unique<SubtractOperation>());
    cout << "Subtraction: " << subCalc.getResult(10, 5) << endl; // 输出5

    // 新增乘法运算,无需修改Calculator或Operation类
    Calculator mulCalc(make_unique<MultiplyOperation>());
    cout << "Multiplication: " << mulCalc.getResult(10, 5) << endl; // 输出50

    return 0;
}

改进设计的优势

  1. 对扩展开放:新增运算(如除法、取模)时,仅需定义新的派生类(如DivideOperation),无需修改现有代码。
  2. 对修改关闭:现有运算类(如AddOperation)和计算器类Calculator的代码无需变动,降低了引入错误的风险。
  3. 符合SOLID原则:与依赖倒置原则(DIP)结合,高层模块(Calculator)依赖抽象(Operation),而非具体实现。

关键点总结

  • 抽象基类:定义接口,约束派生类行为。
  • 多态调用:通过基类指针或引用调用派生类方法,实现运行时绑定。
  • 智能指针:使用unique_ptr管理动态内存,避免内存泄漏。

通过这种设计,系统能够灵活应对需求变化,同时保持代码的稳定性和可维护性。

posted on 2026-01-03 19:42  四季萌芽V  阅读(1)  评论(0)    收藏  举报

导航