派生类中非模板方法的模板方法

时间:2011-01-01 19:54:53

标签: c++ templates class derived

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);

4 个答案:

答案 0 :(得分:6)

有两个原因 -

  1. 在C ++中,如果基类函数标记为虚拟,则成员函数仅覆盖基类成员函数。否则,C ++将两者视为巧合具有相同名称的独立函数。这与Java形成对比,Java中的函数自动覆盖基类函数。

  2. 在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 *,那么你会期望它的版本被调用。