如何在非模板类中使用模板类(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
相关产品推荐
相关产品推荐

