我遇到了同样的问题,但实际上我想出了一个可行的解决方案。展示解决方案的最佳方式是通过示例:
我们想要的(不起作用,因为您不能拥有虚拟模板):
class Base
{
template <class T>
virtual T func(T a, T b) {};
}
class Derived
{
template <class T>
T func(T a, T b) { return a + b; };
}
int main()
{
Base* obj = new Derived();
std::cout << obj->func(1, 2) << obj->func(std::string("Hello"), std::string("World")) << obj->func(0.2, 0.1);
return 0;
}
解决方案(打印3HelloWorld0.3):
class BaseType
{
public:
virtual BaseType* add(BaseType* b) { return {}; };
};
template <class T>
class Type : public BaseType
{
public:
Type(T t) : value(t) {};
BaseType* add(BaseType* b)
{
Type<T>* a = new Type<T>(value + ((Type<T>*)b)->value);
return a;
};
T getValue() { return value; };
private:
T value;
};
class Base
{
public:
virtual BaseType* function(BaseType* a, BaseType* b) { return {}; };
template <class T>
T func(T a, T b)
{
BaseType* argA = new Type<T>(a);
BaseType* argB = new Type<T>(b);
BaseType* value = this->function(argA, argB);
T result = ((Type<T>*)value)->getValue();
delete argA;
delete argB;
delete value;
return result;
};
};
class Derived : public Base
{
public:
BaseType* function(BaseType* a, BaseType* b)
{
return a->add(b);
};
};
int main()
{
Base* obj = new Derived();
std::cout << obj->func(1, 2) << obj->func(std::string("Hello"), std::string("World")) << obj->func(0.2, 0.1);
return 0;
}
我们使用BaseType 类来表示您通常在模板中使用的任何数据类型或类。您将在模板中使用的成员(可能还有运算符)在此处使用虚拟标签进行描述。请注意,为了使多态起作用,指针是必需的。
Type 是扩展Derived 的模板类。这实际上代表了一个特定的类型,例如Type<int>。这个类非常重要,因为它允许我们将任何类型转换为BaseType。我们在BaseType中描述的成员的定义在这里实现。
function 是我们要重写的函数。我们不使用真正的模板,而是使用指向BaseType 的指针来表示类型名。实际的模板函数在定义为func 的Base 类中。它基本上只是调用function 并将T 转换为Type<T>。如果我们现在从 Base 扩展并覆盖 function,则会为派生类调用新的覆盖函数。