Question

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);
Was it helpful?

Solution

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.

OTHER TIPS

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?

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.

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top