Skip to content
UniCircle
MediumConceptualInheritance

The diamond problem in multiple inheritance

Question OOP-105

What is the diamond problem? Show how it arises in C++, how C++ solves it with virtual inheritance, and how Java avoids it — including the case of default methods in interfaces.

Show hints

Draw class A at the top, B and C in the middle, D at the bottom.

Show the explanation

Model answer. The diamond problem appears when a class inherits from two classes that share a common base:

      A
     / \
    B   C
     \ /
      D

If A has a member x and method show(), and both B and C inherit from A, then D receives A's members through two paths. Two questions arise: does D contain one or two copies of A's data, and which version of an inherited method should a call on D use?

In C++ (without a fix)

  • With ordinary inheritance class B : public A and class C : public A, a D object contains two separate A subobjects.
  • d.x or d.show() is a compile-time ambiguity error; you must qualify it as d.B::x or d.C::x, and the two copies can drift apart.

C++ solution: virtual inheritance

C++
class B : virtual public A { };
class C : virtual public A { };
class D : public B, public C { };
  • Now D has a single shared A subobject.
  • The most-derived class (D) is responsible for calling A's constructor.
  • If B and C both override a virtual function of A and D does not, the call is still ambiguous; D must provide its own override.

Java's approach

  • Java simply disallows multiple inheritance of classes: a class can extend only one class, so there is no state to duplicate.
  • A class can implement multiple interfaces. Interfaces have no instance fields, so the data half of the problem cannot occur.
  • With Java 8 default methods, the behaviour half can reappear: if interfaces B and C both declare default void show(), a class implementing both must override `show()`, otherwise it does not compile. Inside, it can choose explicitly with B.super.show().
  • If one default comes from a more specific interface (one extends the other), the more specific one wins; methods from a superclass always win over interface defaults.

Follow-up: "What about Python?" It allows multiple inheritance and resolves method lookup with C3 linearisation (ClassName.__mro__).

Original UniCircle question. Last reviewed 28 Oct 2026.