You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++避免代码重复:跨项目复用类并使用不同对象实例的最优方法

嘿,这个问题我太熟悉了——预处理器指令确实能临时解决问题,但绝对不是最佳实践,毕竟它是编译时硬编码的方式,灵活性差还不好维护。下面给你几个行业内常用的优雅方案,完全不需要依赖预处理器:

最佳实现方案

1. 构造函数依赖注入(最推荐)

这是最符合依赖倒置原则的做法,把需要替换的对象实例通过父类的构造函数传入,子类或者调用方可以自由传入不同的实例,完美实现跨项目复用。

举个C++的示例(其他语言思路一致):

// 可复用的基类(放在公共项目中)
class BaseService {
protected:
    SomeInterface* m_dependency;
public:
    // 构造函数注入依赖接口
    BaseService(SomeInterface* dependency) : m_dependency(dependency) {}
    
    // 基类封装的复用业务逻辑
    void doWork() {
        m_dependency->execute();
    }
};

// 项目A中的子类(继承基类,传入项目专属实例)
class ProjectAService : public BaseService {
public:
    ProjectAService() : BaseService(new ProjectASpecificImpl()) {}
};

// 项目B中的子类(传入另一个专属实例)
class ProjectBService : public BaseService {
public:
    ProjectBService() : BaseService(new ProjectBSpecificImpl()) {}
};

这种方式完全解耦了基类和具体依赖,不同项目只需要实现SomeInterface的专属类,然后在子类构造时传入即可,而且非常方便单元测试(比如传入Mock对象)。

2. 模板方法模式 + 延迟实例化

如果不想在构造阶段传入依赖,也可以在基类中定义抽象方法,让子类负责创建具体的对象实例,基类只专注于复用业务逻辑:

class BaseService {
protected:
    // 子类必须实现这个方法,返回自身需要的对象实例
    virtual SomeInterface* createDependency() = 0;
    
public:
    void doWork() {
        auto dependency = createDependency();
        dependency->execute();
        // 注意内存管理,推荐用智能指针替代裸指针
        delete dependency;
    }
};

class ProjectAService : public BaseService {
protected:
    SomeInterface* createDependency() override {
        return new ProjectASpecificImpl();
    }
};

这种方式把对象创建的责任完全交给子类,基类的业务逻辑可以毫无改动地复用在不同项目中。

3. 策略模式(适合多场景行为替换)

如果需要替换的不只是单个对象,而是一整套业务行为,策略模式会是更合适的选择:

// 定义策略接口(公共项目中)
class BusinessStrategy {
public:
    virtual void execute() = 0;
};

// 基类持有策略对象,封装复用逻辑
class BaseService {
protected:
    BusinessStrategy* m_strategy;
public:
    BaseService(BusinessStrategy* strategy) : m_strategy(strategy) {}
    
    void doWork() {
        m_strategy->execute();
    }
};

// 项目A的专属策略
class ProjectAStrategy : public BusinessStrategy {
public:
    void execute() override {
        // 项目A的具体业务逻辑
    }
};

这种方式甚至支持运行时动态切换策略,灵活性远胜于预处理器指令。

为什么不推荐预处理器指令?

  • 编译时绑定:无法在运行时切换实例,一旦编译完成就无法修改;
  • 可读性差:宏定义散落在代码中,调试和维护都很困难;
  • 违反开闭原则:修改依赖需要修改基类代码或宏定义,而不是通过扩展子类实现。

内容的提问来源于stack exchange,提问作者DavidGo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 09:49:24