3
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[]) { ... }
};

Why does function B::func() not take precedence over the function template A::func() when calling this code?

uint32_t values[5];
A* obj = new B();
obj->func(5, values);
sbi
  • 219,715
  • 46
  • 258
  • 445
mnn
  • 1,952
  • 4
  • 28
  • 51

4 Answers4

6

Two reasons-

  1. In C++ a member function only overrides a base class member function if the base class function is marked virtual. Otherwise, C++ treats the two as independent functions that coincidentally have the same name. This contrasts with Java, where functions atomatically override base class functions.

  2. In C++, template member functions can't be marked virtual. This is partly due to the implementation of virtual functions that's most commonly used - vtables - combined with the C++ template instantiations system. C++ treats all instantiations of the same template over different type arguments as separate functions, and generates these instantiations lazily. This is a problem for the vtable implementation, since a vtable requires static, compile-time determination of the number of different virtual functions in a class, along with an ordering on them. Since a template virtual function would mean an unknown number and ordering of virtual functions in the class, C++ disallows this.

templatetypedef
  • 362,284
  • 104
  • 897
  • 1,065
  • re #2 see also [my answer](http://stackoverflow.com/questions/2354210/can-a-member-function-template-be-virtual/2354671#2354671) to an FAQ entry. – sbi Jan 01 '11 at 20:15
  • So the only solution to my problem is to make non-template version of func in A (calling template function) and override it in B? – mnn Jan 01 '11 at 20:25
  • That should work. Out of curiosity, why do you have a template member function that produces data of arbitrary types? – templatetypedef Jan 01 '11 at 20:26
  • That's just one use case of that function. – mnn Jan 01 '11 at 20:31
1

If you call func on a object/pointer/reference of type A, A::func gets called, since func is not virtual (and it cannot be: it's a template function).

Did you really test your code?

peoro
  • 25,562
  • 20
  • 98
  • 150
0

A::func() isn't declared as virtual, so the compiler won't generate the virtual table and any other code required to invoke B::func() at runtime. It has nothing to do with templates.

chrisaycock
  • 36,470
  • 14
  • 88
  • 125
0

Because B::func is NOT an overload of A::func and can never be, no matter what you do. Don't even try declaring A::func virtual because you can't. Whatever it is you're trying to do, you can't. Static and dynamic polymorphism just don't mix in C++.

If your pointer was to a B*, instead of an A*, you would expect it's version to be called.

Edward Strange
  • 40,307
  • 7
  • 73
  • 125