Pregunta

A multiple inheritance problem in C++:

It looks like a diamond problem, but it is not. It cannot be solved by adding virtual inheritance.

struct A {
   virtual void f() { cout << "A::f()" << endl; };
};

struct B : public virtual A {
   void f() { cout << "B::f()" << endl;};
};

struct C :  public virtual A {
  void f() { cout << "C::f()" << endl;};
};

struct D : B, C { };

int main() {
  D d;

  B* bp = &d;
  A* ap = bp;
  D* dp = &d;

  ap->f();
  dp->f(); // compile error here because D has two candidates f() to override. 
        // error: request for member f is ambiguous
        // error: candidates are: virtual void C::f()
        // error:                 virtual void B::f()

  }

Am I right?

¿Fue útil?

Solución

It looks like a diamond problem, but it is not.

Yes it is; that's the classic "diamond" pattern. Perhaps you mean, the problem isn't caused by the presence of the diamond? That's certainly true, so I wonder why you included that red herring in the question. You'll get the same issue from a simpler example:

struct B {
   virtual void f() { cout << "B::f()" << endl;};
};

struct C {
   virtual void f() { cout << "C::f()" << endl;};
};

struct D : B, C { };

compile error here because D has two candidates f() to override.

No, the error is because D doesn't override them, so there are two candidates for the function call. The virtual function is overridden in both direct base classes, but not in the derived class, so there is no unique final overrider.

You need to decide what D::f() is supposed to do, and implement it accordingly.

Otros consejos

The error isn't in the line you've indicated, but in the very class definition of D. The definition is simply incorrect because there is no unique final overrider for the virtual function.

You have 2 functions with the same signature coming from class B and C, thus the member function f() is ambiguous(which you have already pointed out).

Perhaps there is implicit cast by ap = bp such that ap->f() will be recognized as B::f, but dp has two f()'s to choose from.

edit: can anyone explain why ap->f() wouldn't throw error but dp->f() would?

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top