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

如何定义管理抽象基类子类数组的Multi类并实现有效初始化

解决方案

我们可以通过将Multi模板绑定到具体子类类型,同时添加编译期约束确保它仅接受A<T>的派生类,既满足类型安全,又能实现便捷初始化。

核心实现思路

  • 给Multi新增模板参数Derived,明确指定要管理的子类(如B<T>、C<T>)
  • 用std::is_base_of_v做编译期检查,限制Derived必须继承自A<T>
  • 提供两种初始化方式:直接通过子类类型创建对象(无需临时实例)、通过子类实例拷贝创建
  • 内部用std::array<std::unique_ptr<A<T>>, N>存储多态对象,保证do_something()的多态调用

完整代码实现

#include <array>
#include <memory>
#include <type_traits>

template <typename T>
class A {
public:
    virtual void do_something() = 0;
    virtual ~A() = default; // 基类必须声明虚析构,避免内存泄漏
};

template <typename T>
class B : public A<T> {
public:
    void do_something() override {}
};

template <typename T>
class C : public A<T> {
public:
    void do_something() override {}
};

template <typename T, int N, typename Derived>
class Multi {
    // 编译期约束:确保Derived是A<T>的子类
    static_assert(std::is_base_of_v<A<T>, Derived>, "Derived must inherit from A<T>");
public:
    // 方式1:直接传入子类类型,默认构造N个对象
    explicit Multi(std::type_identity_t<Derived>) {
        for (auto& ptr : _objs) {
            ptr = std::make_unique<Derived>();
        }
    }

    // 方式2:传入子类实例,拷贝构造N个对象
    explicit Multi(const Derived& prototype) {
        for (auto& ptr : _objs) {
            ptr = std::make_unique<Derived>(prototype);
        }
    }

    void do_something() {
        for (auto& ptr : _objs) {
            ptr->do_something();
        }
    }

private:
    std::array<std::unique_ptr<A<T>>, N> _objs;
};

// 辅助推导指南,简化模板参数书写
template <typename T, int N, typename Derived>
Multi(std::type_identity_t<Derived>) -> Multi<T, N, Derived>;

template <typename T, int N, typename Derived>
Multi(const Derived&) -> Multi<T, N, Derived>;

使用示例

// 无需临时对象,直接创建3个C<double>对象
auto cm = Multi<double, 3>(std::type_identity<C<double>>{});

// 通过已有实例,拷贝创建5个B<long>对象
B<long> b_instance;
auto bm = Multi<long, 5>(b_instance);

// 批量调用方法
cm.do_something();
bm.do_something();

关键细节说明

  • 基类A<T>必须声明虚析构函数,否则unique_ptr<A<T>>无法正确调用子类析构,会引发内存泄漏
  • std::type_identity用于明确传递类型,避免编译器推导歧义
  • 编译期断言static_assert提前拦截非法类型,提升代码安全性
  • 推导指南让调用时无需手动写全模板参数,简化代码

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 13:42:46