(1) 有点,但不完全是您尝试的方式。您基本上希望专业化来定义功能;这与声明基类和派生类时有很大不同。
template <typename T> class Shape {
static_assert(false, "Not implemented");
};
template <> class Shape<bool> {
void Foo(bool a, std::string b) {...}
};
template <> class Shape<int> {
void Foo(int, std::string, whatever else) {...}
};
即使您要在原始的非特化 Shape 中定义 Foo,它也不会影响特化。完全专业化不会扩展原始模板,而是替换它!
(2) 使用静态断言。请参见上面的示例。
(3) 是的,您可以混合使用模板和继承。虚函数运行时多态和静态多态。模板参数必须在编译时知道,而运行时多态对象的确切类型则不需要,因为它们可以被基类引用引用。在上面的模板示例中,您不能简单地说
template <class T> Shape {...};
...
Shape* myShape; // Compiler error: Shape requires a template parameter
但是,通过继承,您可以:
class ShapeBase { virtual void Foo() = 0; };
class Circle : public ShapeBase { virtual void Foo() { ... } };
class Square : public ShapeBase { virtual void Foo() { ... } };
...
Shape* myShape = new Circle;
myShape->Foo(); // calls Circle->Foo()
请注意,当您使用继承时,函数签名必须匹配!这就是您将决定推迟到运行时所付出的代价。