I have the following problem. A class E
overrides two methods: one comes from an abstract class D
which inherits from a specialization of a templated class C<T>
where T = A
. The other is from C<A>
directly. And both have the same name.
Now, D
should have access to both methods: doSomething(const A& a)
because it inherits it from C
, and doSomething(const B& b)
because D
declares it.
However, the following code does not compile, because the compiler recognizes only the method doSomething(const B&)
from the pointer to D
#include <iostream>
#include <sstream>
using namespace std;
class A {
private:
int a = 10;
public:
inline std::string hello() const{
std::stringstream ss;
ss << a;
return ss.str();
}
};
class B {
private:
int b = 20;
public:
inline std::string hello() const{
std::stringstream ss;
ss << b;
return ss.str();
}
};
template <class T>
class C {
public:
inline virtual bool doSomething(const T& t) {
std::cout << "C is doing something with T" << t.hello() << std::endl;
return true;
}
};
class D : public C<A> {
public:
virtual void doSomething(const B& b) = 0;
};
class E : public D {
public:
inline bool doSomething(const A& a) override {
std::cout << "E is doing something with A: " << a.hello() << std::endl;
return true;
}
inline void doSomething(const B& b) override {
std::cout << "E is doing somethign with B: " << b.hello() << std::endl;
}
};
int main()
{
A a;
B b;
D* d = new E();
d->doSomething(b);
d->doSomething(a); // compile error, does not recognize doSomething(const A&)
delete d;
}
The compiler shows the following error:
In function ‘int main()’:
main.cpp:62:19: error: no matching function for call to ‘D::doSomething(A&)’
d->doSomething(a); // compile error, does not recognize doSomething(const A&)
^
main.cpp:39:18: note: candidate: virtual void D::doSomething(const B&)
virtual void doSomething(const B& b) = 0;
^
main.cpp:39:18: note: no known conversion for argument 1 from ‘A’ to ‘const B&’
Why is that?
This happens because compiler does not automatically merge all the functions from the base classes to the set of overloaded functions to select from. That is the set of overloaded functions considered when you call d->doSomething(a);
consists only of D::doSomething(const B& b)
. In order to fix this you need to bring C<A>::doSomething;
into D
class
class D : public C<A> {
public:
using C<A>::doSomething;
virtual void doSomething(const B& b) = 0;
};