Harper
Harper

Reputation: 1964

When using template and inheritance together, I do not know how to override a member function

I have the following code that mixes template and inheritance.

Class Base has some utility function to build items (the work in the sample code), and Child call the work in its implementation of the API call.

In this function

virtual void call() override {
        Base<T>::work(); // Problem Here
        // work();
}

I try to call work() but got the following error:

test.cc: In member function ‘virtual void Child<T>::call()’:
test.cc:18:2: error: there are no arguments to ‘work’ that depend on a template parameter, so a declaration of ‘work’ must be available [-fpermissive]

So I write Base<T>::work() and makes it work.

Now I have a Grandson class, who want to override the work function. But the override does not work as in Child<T>::call I have explicitly specified calling Base<T>::work(). So what's the correct way to implement Child<T>::call to make the override in Grandson work?

#include <iostream>

template <typename T>
class Base {
protected:
    virtual void work() {
        T a;
        std::cout << "From Base" << '\n';
    }
public:
    virtual void call() = 0;
};

template <typename T>
class Child : public Base<T> {
public:
    virtual void call() override {
        Base<T>::work(); // Problem Here
        // work();
    }
};

template <typename T>
class Grandson : public Child<T> {
        protected:
                void work() override {
                        std::cout << "From Grandson" << '\n';
                }
};

int main() {
        Grandson<int> g;
        g.call();
}

Upvotes: 1

Views: 51

Answers (1)

Justin
Justin

Reputation: 25297

Replace Base<T>::work() with this->work().


When you are a template class inheriting from a base class dependent on your template parameter, the compiler doesn't look into your base when it sees something like work(). Instead, you have to tell it that it needs to do that. The easiest way I know of to accomplish that is to prefix the call with this->.

As for why it does not work when you use Base<T>::work(), I am not entirely sure. It's hardcoding it to call the base class implementation, but I'm fairly sure there's a similar syntax that does work.

Upvotes: 2

Related Questions