David Doria
David Doria

Reputation: 10273

Ambiguous base with multiple inheritance

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

Answers (4)

AnT stands with Russia
AnT stands with Russia

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

John Humphreys
John Humphreys

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

Seth Carnegie
Seth Carnegie

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

templatetypedef
templatetypedef

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

Related Questions