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

如何在非模板类中使用模板类(C++)

解决方案:抽象基类+多态实现非模板类持有模板类实例

可以通过抽象基类+多态的方式实现需求,既保持MyClass为非模板类,又能持有不同模板参数的TemplateClass实例,同时MyClass的方法可以移到源文件中实现。

步骤1:定义非模板抽象基类

先创建一个非模板的抽象基类,声明TemplateClass需要对外暴露的统一接口:

// ITemplateInterface.h
class ITemplateInterface {
public:
    virtual ~ITemplateInterface() = default; // 必须声明虚析构,避免内存泄漏
    // 这里添加TemplateClass需要对外提供的方法,示例如下:
    virtual void doSomething() = 0;
    // 可根据实际需求添加更多纯虚函数
};

步骤2:修改模板类继承抽象基类

让TemplateClass继承上述抽象基类,并实现接口中的纯虚函数:

// TemplateClass.h
#include "ITemplateInterface.h"
#include <iostream>

template <int A, int B>
class TemplateClass : public ITemplateInterface {
public:
    // 原有的TemplateClass成员和逻辑
    void doSomething() override {
        // 实现具体逻辑,可直接使用模板参数A、B
        std::cout << "Template parameters: A=" << A << ", B=" << B << std::endl;
    }
    // ...其他成员方法或属性
};

步骤3:重构非模板类MyClass

MyClass持有抽象基类的指针,在构造函数中根据传入的参数创建对应模板实例:

// MyClass.h
#include "ITemplateInterface.h"
#include <memory> // 使用智能指针避免手动内存管理

class MyClass {
private:
    std::unique_ptr<ITemplateInterface> tc; // 用unique_ptr替代裸指针,更安全
public:
    MyClass(int a, int b);
    // 析构函数可省略,unique_ptr会自动释放内存
    void callDoSomething(); // 转发调用模板类的方法

    // 禁止拷贝构造和赋值,避免指针重复释放问题
    MyClass(const MyClass&) = delete;
    MyClass& operator=(const MyClass&) = delete;
    // 支持移动构造和赋值
    MyClass(MyClass&&) = default;
    MyClass& operator=(MyClass&&) = default;
};
// MyClass.cpp
#include "MyClass.h"
#include "TemplateClass.h"
#include <stdexcept>

MyClass::MyClass(int a, int b) {
    // 根据传入的a、b值,创建对应模板参数的TemplateClass实例
    // 注意:此方式适用于a、b的可能取值有限且已知的场景
    if (a == 1 && b == 2) {
        tc = std::make_unique<TemplateClass<1, 2>>();
    } else if (a == 3 && b == 4) {
        tc = std::make_unique<TemplateClass<3, 4>>();
    } else {
        throw std::invalid_argument("Unsupported A/B parameter values");
    }
}

void MyClass::callDoSomething() {
    tc->doSomething();
}

关键注意事项

  • 抽象基类必须包含虚析构函数,否则通过基类指针删除派生类实例时会触发未定义行为,导致内存泄漏。
  • 如果模板参数A、B的可能取值是无限的,上述枚举判断的方式不适用,此时可以结合C++17的std::variant存储不同模板实例,再通过访问者模式处理不同类型的逻辑。
  • 使用std::unique_ptr替代裸指针,无需手动管理内存,减少内存泄漏风险。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 05:37:37