I'm struggling a bit to understand why this code snippet does not compile.
#include <cstdio>
class A {
public:
virtual int potential()=0;
virtual int potential(int arg, int arg2)=0;
};
class B : public A {
public:
int potential() { return 1; }
virtual int potential(int arg, int arg2) { return 2; }
};
class C : public B {
public:
int potential(int arg, int arg2) { return 3; }
};
int main(int argc, char** argv) {
C c;
int value = c.potential();
printf("Got %i\n", value);
return 0;
}
I have two pure virtual methods, both named potential
in the abstract superclass A
. The subclass B
then defines both, but a further subclass C
only needs to redefine one of the methods.
However, on compilation, only the method defined in C
is recognized, and potential()
isn't seen (this should have been inherited from B
):
In function 'int main(int, char**)':
Line 23: error: no matching function for call to 'C::potential()'
compilation terminated due to -Wfatal-errors.
If I rename A::potential(int, int)
to something else all the way down the inheritance tree, such as A::somethingElse(int, int)
, then the code compiles fine, and the output is Got 1
, as expected.
This has been verified using clang, g++ and MSVC's cl.
Any ideas on what is going on?
However, on compilation, only the method defined in C is recognized, and potential() isn't seen (this should have been inherited from B).
C++ doesn’t work like this: because you implemented a different potential
method (a method of the same name but with different parameters) in C
, the other method is hidden as far as C
is concerned.
Hiding happens because of the way that C++ resolves (overloaded) method names: when you call a method potential
on an instance of a class (here c
), C++ searches in the class whether a method of that name exists. If that isn’t the case it continues its search in the base classes. It goes further up in the hierarchy until at least one method of that name is found.
But in your case, C++ doesn’t have to search far: the method already exists in C
, so it stops its search. Now C++ tries to match the method signature. Unfortunately, the method signature doesn’t match but at this time it’s too late: overload resolution fails; C++ doesn’t search for other methods that might match.
There are three solutions:
Import it with using
in C:
class C : public B {
public:
using B::potential;
int potential(int arg, int arg2) { return 3; }
};
Call the method from a base class instance in main
:
C c;
B& b = c;
int value = b.potential();
Qualify the name explicitly in main
:
C c;
int value = c.B::potential();
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With