Reputation: 10273
I am trying to write some subclasses of classes in a big library. I am getting an "ambiguous base" error. Here is a compilable example of the problem:
#include <iostream>
// I can't change these because they are in the library:
class InteractorStyle {};
class InteractorStyleCamera : public InteractorStyle {};
class InteractorStyleImage : public InteractorStyle {};
// These are my subclasses (so I can change them):
class PointSelector : public InteractorStyle {};
class PointSelector2D : public InteractorStyleCamera, public PointSelector
{
// This function has to exist exactly like this (a requirement of the library):
static PointSelector2D* SafeDownCast(InteractorStyle *o)
{
return static_cast<PointSelector2D *>(o);
}
};
int main()
{
return 0;
}
The error is
error: ‘InteractorStyle’ is an ambiguous base of ‘PointSelector2D’.
Is there anything I can do in this case?
Upvotes: 28
Views: 47760
Reputation: 320641
You can superficially "fix" it by using a two-step cast. For example
static_cast<PointSelector2D *>(static_cast<InteractorStyleCamera *>(o));
Of course, you have to keep in mind that this "fixes" the syntax, but doesn't fix the underlying structural problem. Your PointSelector2D
has two InteractorStyle
base subobjects inside. Depending from which InteractorStyle
base subobjects you start, the upcast path is different. And it is very important to take the correct path. What I wrote above is for InteractorStyle
inside InteractorStyleCamera
. For the other base the proper upcast would be
static_cast<PointSelector2D *>(static_cast<PointSelector *>(o));
If you are just given an InteractorStyle *
pointer with no extra information about which base it is pointing to, then you can't possibly solve your problem with static_cast
. There's no way to know which upcast path to take. Taking the wrong one will produce a totally meaningless result.
As it has been noted already, dynamic_cast
can help in this situation, but it has additional requirements (polymorphic starting type). Your types are not polymorphic (at least in your quoted example), so dynamic_cast
will not accept them for upcasts.
Upvotes: 6
Reputation: 39314
Your problem is that Interactor style is inherited twice - once by PointSelector2D and once by InteractorStyleCamera. This means that you have 2 versions of every member of it contained within your class.
Check out:
How can I avoid the Diamond of Death when using multiple inheritance?
And try virtual inheritance.
Upvotes: 21
Reputation: 75150
You can get your code to compile (I got your example to compile at least) by adding InteractorStyle
to the classes that PointSelector2D
inherits from. Whether this is a long term solution is not known by me.
Upvotes: 0
Reputation: 373002
I believe you can fix this by using a dynamic_cast
instead of a static_cast
. The dynamic_cast
can look at the object at runtime to determine which of the two InteractorStyle
base classes is being pointed at, and from there can adjust the pointer down to the appropriate type.
Upvotes: 3