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

C++中如何通过字符串自动实例化第三方库的不同子类?

Solution 1: Registry-Based Factory (Template Metaprogramming)

This approach uses a singleton registry to map type strings to factory functions, with template helpers to automate registration of each derived class—no need to hardcode if-else chains.

#include <memory>
#include <unordered_map>
#include <functional>
#include <string>

// Third-party classes (unchanged)
class obj
{
public:
    virtual std::string type() = 0;
};

class subobj01 : public obj
{
public:
    std::string type() override { return "subobj01"; }
};

class subobj02 : public obj
{
public:
    std::string type() override { return "subobj02"; }
};

class subobj03 : public obj
{
public:
    std::string type() override { return "subobj03"; }
};

// Registry to map type names to factory functions
class ObjectFactoryRegistry {
public:
    using FactoryFunc = std::function<std::shared_ptr<obj>()>;

    // Singleton instance
    static ObjectFactoryRegistry& instance() {
        static ObjectFactoryRegistry registry;
        return registry;
    }

    // Register a factory for a specific type
    void register_factory(const std::string& type_name, FactoryFunc func) {
        factories_[type_name] = std::move(func);
    }

    // Create an instance from a type string
    std::shared_ptr<obj> create(const std::string& type_name) const {
        auto it = factories_.find(type_name);
        if (it != factories_.end()) {
            return it->second();
        }
        return nullptr; // Or throw std::invalid_argument for unknown types
    }

private:
    ObjectFactoryRegistry() = default;
    std::unordered_map<std::string, FactoryFunc> factories_;
};

// Template helper to auto-register derived classes
template <typename Derived>
class FactoryRegistrar {
public:
    explicit FactoryRegistrar(const std::string& type_name) {
        ObjectFactoryRegistry::instance().register_factory(
            type_name, []() { return std::make_shared<Derived>(); }
        );
    }
};

// Register each third-party subclass (run once at program startup)
static FactoryRegistrar<subobj01> registrar_subobj01("subobj01");
static FactoryRegistrar<subobj02> registrar_subobj02("subobj02");
static FactoryRegistrar<subobj03> registrar_subobj03("subobj03");

// Your desired create_instance function
std::shared_ptr<obj> create_instance(std::shared_ptr<obj> o) {
    if (!o) return nullptr;
    return ObjectFactoryRegistry::instance().create(o->type());
}

Key Details:

  • The ObjectFactoryRegistry singleton stores factory functions for each derived class.
  • The FactoryRegistrar template automates registering each class's factory (std::make_shared<Derived>) when the program starts.
  • Adding new derived classes only requires a new FactoryRegistrar instance—no changes to the core factory logic.

Solution 2: Variant-Based Return (Strongly Typed Derived Instances)

If you need to work with specific derived types without manual casting, return a std::variant containing the derived shared pointers. Use std::visit to handle each type explicitly.

#include <variant>
#include <stdexcept>
#include <iostream>

// Define a variant type covering all derived classes
using ObjVariant = std::variant<
    std::shared_ptr<subobj01>,
    std::shared_ptr<subobj02>,
    std::shared_ptr<subobj03>
>;

ObjVariant create_instance_variant(std::shared_ptr<obj> o) {
    if (!o) throw std::invalid_argument("Null input object");

    const std::string& type = o->type();
    if (type == "subobj01") {
        return std::make_shared<subobj01>();
    } else if (type == "subobj02") {
        return std::make_shared<subobj02>();
    } else if (type == "subobj03") {
        return std::make_shared<subobj03>();
    }

    throw std::invalid_argument("Unknown object type: " + type);
}

// Example usage with std::visit
void process_new_instance(ObjVariant variant) {
    std::visit([](auto ptr) {
        std::cout << "Created instance of type: " << ptr->type() << "\n";
        // Add type-specific logic here (ptr is strongly typed to the derived class)
    }, variant);
}

Key Details:

  • ObjVariant acts as a type-safe container for any of the derived shared pointers.
  • std::visit eliminates the need for manual dynamic_cast by dispatching to a handler that works with each derived type directly.

内容的提问来源于stack exchange,提问作者J.W Kang

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 05:39:24