Reputation: 41
I am facing inheritance hierarchy error which I root caused to this code snippet. The definition of l() is defined in Template class Y, I don't understand why is the compiler finding it ambiguous.Class Z ptr_ is pointing to class Y object which has the definition of l() isn't this how it should work ?
Unfortunately the base classes are all part of a static library, class C is the only thing under my control . I am not sure what I can do here.
Error:
Line 84: Char 13: error: non-static member 'l' found in multiple base-class subobjects of type 'D':
class C -> class A -> class D
class C -> class B -> class D
ptr_->l ()
Line 96: Char 15: note: in instantiation of member function 'Z<C>::~Z' requested here
Z < C > t = new Y < C > ();
^
Line 31: Char 16: note: member found by ambiguous name lookup
virtual void l () = 0;
#include <iostream>
using namespace std;
template <class T>
class Y : public T {
public:
void l() {}
void p() {}
};
class D {
public:
virtual void l() = 0;
virtual void p() = 0;
};
class A : public D {
public:
virtual void f(int a) = 0;
virtual void d() = 0;
};
class B : public D {
public:
virtual void j(string x) = 0;
virtual void d() = 0;
};
class C : public A, public B {
public:
void f(int a) override {}
void j(string x) override {}
void d() override {}
};
template <class T>
class Z {
public:
Z(T *ptr) : ptr_(ptr) {}
~Z() {
if (ptr_)
ptr_->l();
}
protected:
T *ptr_;
};
int main() {
Z<C> t = new Y<C>();
return 0;
}
Upvotes: 0
Views: 553
Reputation: 3983
Your problem is that you have an inheritance hierarchy that looks like this:
C
/ \
A B
| |
D D <- Defines l()
So when you call l()
through a C
type, then the compiler don't know if you want to call C::A::D::l()
or C::B::D::l()
.
One way to fix this is to specify which branch you actually want to use in the C
class.
The compiler complains in your example because l()
is abstract in D
, however if that isn't the case in your "real" code, then this works to fix the ambiguity:
class C : public A, public B {
public:
...
virtual void l() override { A::l(); } // Or B::l() if you prefer, of course
};
But if l()
is abstract in D
, and isn't implemented in A
or B
, then you can do this in C
:
class C : public A, public B {
public:
...
virtual void l() = 0;
};
Upvotes: 1