Reputation: 1964
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
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