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

C++运行时动态创建指定类型对象:多态与模板的困境及求解

解决方案

针对你这种已知有限类型(2-5种)的场景,有几种简单的实现方式,不需要复杂的泛型或std::variant:

方法1:多态父类提供类型专属访问接口

在父类中为每种已知类型定义对应的虚访问函数,子类重写自己类型对应的函数,安全获取数据:

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

struct Parent {
    virtual ~Parent() = default; // 必须声明虚析构,确保子类析构函数被调用
    virtual void print_type() = 0;
    // 为每种已知类型定义专属getter
    virtual int* get_int() { return nullptr; }
    virtual float* get_float() { return nullptr; }
};

template<class T>
struct Child : public Parent {
    T data;

    void print_type() override {
        cout << typeid(T).name() << endl;
    }
};

// 特化int子类的get_int方法
template<>
int* Child<int>::get_int() {
    return &data;
}

// 特化float子类的get_float方法
template<>
float* Child<float>::get_float() {
    return &data;
}

unique_ptr<Parent> Factory(int type_code) {
    if (type_code == 0) {
        return make_unique<Child<int>>();
    } else {
        return make_unique<Child<float>>();
    }
}

int main() {
    int type_code;
    cin >> type_code;

    auto p = Factory(type_code);
    p->print_type();

    // 访问并修改数据
    if (int* int_data = p->get_int()) {
        *int_data = 123;
        cout << "Int data: " << *int_data << endl;
    } else if (float* float_data = p->get_float()) {
        *float_data = 45.67f;
        cout << "Float data: " << *float_data << endl;
    }
}

新增类型时,只需在父类添加对应虚函数,再特化子类的实现即可,逻辑直白易维护。

方法2:用dynamic_cast直接转换子类指针

利用C++动态类型转换,拿到父类指针后尝试转换为对应子类指针,成功则直接访问数据:

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

struct Parent {
    virtual ~Parent() = default;
    virtual void print_type() = 0;
};

template<class T>
struct Child : public Parent {
    T data;

    void print_type() override {
        cout << typeid(T).name() << endl;
    }
};

unique_ptr<Parent> Factory(int type_code) {
    if (type_code == 0) {
        return make_unique<Child<int>>();
    } else {
        return make_unique<Child<float>>();
    }
}

int main() {
    int type_code;
    cin >> type_code;

    auto p = Factory(type_code);
    p->print_type();

    // 尝试转换为子类指针并操作数据
    if (auto child_int = dynamic_cast<Child<int>*>(p.get())) {
        child_int->data = 789;
        cout << "Int data: " << child_int->data << endl;
    } else if (auto child_float = dynamic_cast<Child<float>*>(p.get())) {
        child_float->data = 10.11f;
        cout << "Float data: " << child_float->data << endl;
    }
}

这种方式代码更简洁,不需要额外虚函数,缺点是需要显式判断每种类型,但对于2-5种类型的场景完全可以接受。

方法3:极简版类型擦除(用void*)

如果追求极致简单,可在父类用void*存储数据并记录类型标签,手动维护类型安全:

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

enum class DataType { INT, FLOAT };

struct Parent {
    DataType type;
    void* data;
    virtual ~Parent() {
        // 根据类型手动释放内存
        if (type == DataType::INT) {
            delete static_cast<int*>(data);
        } else if (type == DataType::FLOAT) {
            delete static_cast<float*>(data);
        }
    }
    void print_type() {
        cout << (type == DataType::INT ? "int" : "float") << endl;
    }
};

unique_ptr<Parent> Factory(int type_code) {
    auto p = make_unique<Parent>();
    if (type_code == 0) {
        p->type = DataType::INT;
        p->data = new int();
    } else {
        p->type = DataType::FLOAT;
        p->data = new float();
    }
    return p;
}

int main() {
    int type_code;
    cin >> type_code;

    auto p = Factory(type_code);
    p->print_type();

    // 访问并修改数据
    if (p->type == DataType::INT) {
        *static_cast<int*>(p->data) = 1234;
        cout << "Int data: " << *static_cast<int*>(p->data) << endl;
    } else if (p->type == DataType::FLOAT) {
        *static_cast<float*>(p->data) = 56.78f;
        cout << "Float data: " << *static_cast<float*>(p->data) << endl;
    }
}

这种方式不需要模板和子类,缺点是类型安全全靠手动维护,适合类型极少的场景。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 22:15:37