如何创建包含多模板参数类型的模板接口向量?
解决方案:存储不同特化模板接口的派生类到向量
你的核心问题是:ITemplateInterface<T>的不同特化是完全独立的类型,DerivedClass1继承的是ITemplateInterface<std::string>,DerivedClass2继承的是ITemplateInterface<int>,这两个基类之间没有继承关系,因此无法将它们的指针直接存入同一个向量。要解决这个问题,需要引入一个非模板的公共基类来统一类型,再结合类型封装或访问者模式处理不同的返回值。
方法一:使用std::any封装返回值
这种方式灵活,适合派生类类型不确定或较多的场景:
#include <iostream> #include <vector> #include <any> #include <typeinfo> // 定义非模板公共基类,作为所有模板接口的统一父类 class IBaseInterface { public: virtual void foo() = 0; virtual std::any getAnyValue() const = 0; virtual ~IBaseInterface() = default; }; // 模板接口继承自非模板基类 template <typename T> class ITemplateInterface : public IBaseInterface { public: virtual T getValue() const = 0; // 实现基类方法,将强类型值封装为std::any std::any getAnyValue() const override { return getValue(); } using type = T; }; // 派生类1(特化为std::string) class DerivedClass1 : public ITemplateInterface<std::string> { public: void foo() override { std::cout << "DerivedClass1 foo" << std::endl; } std::string getValue() const override { return "Hello from Derived1"; } }; // 派生类2(特化为int) class DerivedClass2 : public ITemplateInterface<int> { public: void foo() override { std::cout << "DerivedClass2 foo" << std::endl; } int getValue() const override { return 42; } }; int main() { // 向量存储非模板基类的指针 std::vector<IBaseInterface*> myVector; DerivedClass1 obj1; DerivedClass2 obj2; myVector.push_back(&obj1); myVector.push_back(&obj2); // 遍历并使用对象 for (auto item : myVector) { item->foo(); std::any value = item->getAnyValue(); // 根据类型取出值并打印 if (value.type() == typeid(std::string)) { std::cout << "Value: " << std::any_cast<std::string>(value) << "\n\n"; } else if (value.type() == typeid(int)) { std::cout << "Value: " << std::any_cast<int>(value) << "\n\n"; } } return 0; }
说明:
- 非模板基类
IBaseInterface提供了统一的接口,让所有派生类可以被放入同一个向量。 ITemplateInterface<T>实现getAnyValue方法,将getValue()的强类型结果封装为std::any,实现类型擦除。- 遍历通过
std::any::type()判断实际类型,再用std::any_cast取出对应值。
方法二:访问者模式(类型安全)
如果派生类类型固定,推荐使用访问者模式,避免类型判断,保证类型安全:
#include <iostream> #include <vector> // 前向声明访问者类 class IVisitor; // 非模板公共基类 class IBaseInterface { public: virtual void foo() = 0; virtual void accept(IVisitor& visitor) = 0; virtual ~IBaseInterface() = default; }; // 访问者基类,枚举所有需要处理的派生类 class IVisitor { public: virtual void visit(DerivedClass1* obj) = 0; virtual void visit(DerivedClass2* obj) = 0; virtual ~IVisitor() = default; }; // 模板接口 template <typename T> class ITemplateInterface : public IBaseInterface { public: virtual T getValue() const = 0; using type = T; }; // 派生类1 class DerivedClass1 : public ITemplateInterface<std::string> { public: void foo() override { std::cout << "DerivedClass1 foo" << std::endl; } std::string getValue() const override { return "Hello from Derived1"; } // 实现accept方法,接受访问者 void accept(IVisitor& visitor) override { visitor.visit(this); } }; // 派生类2 class DerivedClass2 : public ITemplateInterface<int> { public: void foo() override { std::cout << "DerivedClass2 foo" << std::endl; } int getValue() const override { return 42; } void accept(IVisitor& visitor) override { visitor.visit(this); } }; // 具体访问者:打印对象信息 class PrintVisitor : public IVisitor { public: void visit(DerivedClass1* obj) override { obj->foo(); std::cout << "Value: " << obj->getValue() << "\n\n"; } void visit(DerivedClass2* obj) override { obj->foo(); std::cout << "Value: " << obj->getValue() << "\n\n"; } }; int main() { std::vector<IBaseInterface*> myVector; DerivedClass1 obj1; DerivedClass2 obj2; myVector.push_back(&obj1); myVector.push_back(&obj2); PrintVisitor visitor; // 遍历并通过访问者处理每个对象 for (auto item : myVector) { item->accept(visitor); } return 0; }
说明:
- 访问者模式通过
accept方法将对象自身传递给访问者,由访问者根据对象实际类型执行对应逻辑。 - 不需要类型判断,完全类型安全,但需要提前枚举所有可能的派生类,适合派生类固定的场景。
内容的提问来源于stack exchange,提问作者codiac
相关产品推荐
相关产品推荐

