class A {
public:
template<typename T> void func(size_t n, T values[]) { ... }
};
class B : public A {
public:
void func(size_t n, uint32_t values[]) { ... }
};
调用此代码时,为什么函数B::func()
不优先于函数模板A::func()
?
uint32_t values[5];
A* obj = new B();
obj->func(5, values);
答案 0 :(得分:6)
有两个原因 -
在C ++中,如果基类函数标记为虚拟,则成员函数仅覆盖基类成员函数。否则,C ++将两者视为巧合具有相同名称的独立函数。这与Java形成对比,Java中的函数自动覆盖基类函数。
在C ++中,模板成员函数不能标记为虚拟。这部分是由于最常用的虚函数的实现 - vtables - 与C ++模板实例化系统相结合。 C ++将不同类型参数的同一模板的所有实例化视为单独的函数,并且懒惰地生成这些实例化。这是vtable实现的一个问题,因为vtable需要静态编译时确定类中不同虚函数的数量,以及对它们的排序。由于模板虚函数意味着类中未知的数字和虚函数的排序,C ++不允许这样做。
答案 1 :(得分:1)
如果您对func
类型的对象/指针/引用调用A
,则会调用A::func
,因为func
不是虚拟的(并且它不能是:它是模板功能)。
你真的测试了你的代码吗?
答案 2 :(得分:0)
A::func()
未声明为virtual
,因此编译器不会生成虚拟表以及在运行时调用B::func()
所需的任何其他代码。它与模板无关。
答案 3 :(得分:0)
因为B :: func不是A :: func的重载而且永远不会,无论你做什么。甚至不要尝试声明A :: func虚拟,因为你不能。无论你想做什么,你都做不到。静态和动态多态只是不能在C ++中混合。
如果你的指针是B *,而不是A *,那么你会期望它的版本被调用。