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

C++运行时添加用户自定义派生类对象的实现方案问询

运行时实例化自定义派生类的可行方案

问题背景

现有基类Foo:

class Foo{
    virtual void init();
    virtual void update(float dt);
};

用户自定义派生类Bar:

class Bar : public Foo{
    void init() override;
    void update(float dt) override;
};

希望通过配置文件(格式如[Foo] : "Bar")在运行时查询Foo的派生类并实例化Bar对象,此前尝试基于type_info的工厂模式但无法通过type_info创建对象,且已知C++无原生反射,不想使用DLL,实际需求是为基础游戏引擎添加脚本系统。


方案1:手动注册的工厂模式(最常用)

核心是维护类名到创建函数的映射表,所有派生类在编译时主动注册到表中,运行时通过配置类名查表创建对象。

实现步骤

  1. 定义工厂类,包含静态映射表与核心方法:
#include <unordered_map>
#include <string>
#include <memory>

class FooFactory {
private:
    using CreateFunc = std::unique_ptr<Foo>(*)();
    static std::unordered_map<std::string, CreateFunc> creators;

public:
    static void registerCreator(const std::string& className, CreateFunc func) {
        creators[className] = func;
    }

    static std::unique_ptr<Foo> create(const std::string& className) {
        auto it = creators.find(className);
        return it != creators.end() ? it->second() : nullptr;
    }
};

// 初始化静态映射表
std::unordered_map<std::string, FooFactory::CreateFunc> FooFactory::creators;
  1. 派生类添加自动注册逻辑:
class Bar : public Foo{
    void init() override {}
    void update(float dt) override {}

    struct Register {
        Register() {
            FooFactory::registerCreator("Bar", []() {
                return std::make_unique<Bar>();
            });
        }
    };
    static Register registerInstance;
};

// 触发静态注册
Bar::Register Bar::registerInstance;
  1. 运行时解析配置并创建对象:
// 假设解析配置得到类名"Bar"
std::unique_ptr<Foo> obj = FooFactory::create("Bar");
if (obj) {
    obj->init();
    // 后续调用obj->update(dt)
}

方案2:预处理器宏简化注册(减少重复代码)

如果派生类数量多,用宏定义一键完成注册:

#define REGISTER_FOO_DERIVED(className) \
struct className##Register { \
    className##Register() { \
        FooFactory::registerCreator(#className, []() { \
            return std::make_unique<className>(); \
        }); \
    } \
}; \
static className##Register className##_register_instance;

派生类中只需一行代码:

class Bar : public Foo{
    void init() override {}
    void update(float dt) override {}
};
REGISTER_FOO_DERIVED(Bar);

方案3:嵌入脚本语言(适配游戏引擎脚本系统需求)

既然是为引擎做脚本系统,直接嵌入轻量脚本(如Lua)是更贴合需求的方案:

  • 把Foo的接口绑定到脚本,让用户在脚本中编写派生类逻辑;
  • 配置文件指定脚本路径,引擎加载脚本后,通过脚本API创建对象并绑定到C++层;
  • 这种方式无需修改C++代码即可扩展功能,完全符合脚本系统的设计目标。

注意事项

  • 所有派生类需和引擎代码一起编译(因为不用DLL),新增类后需重新编译;
  • 若需热更新,脚本方案是最优选择;
  • 多线程环境下,工厂类的注册、创建方法需加锁保证线程安全。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 03:40:54