class Derived : public Base1, public Base2 lets Derived inherit from both Base1 and Base2 simultaneously — genuinely different from Java's single-class-inheritance restriction. This introduces the diamond problem: if Base1 and Base2 both derive from a common Base, an ordinary Derived object ends up with two separate, independent copies of Base's data, one via each path, which is rarely what's intended. virtual inheritance (marking the inheritance from the shared ancestor as virtual in both Base1 and Base2) fixes this by ensuring only one shared copy of Base exists in the final object.
Basic multiple inheritance
Duck genuinely has both fly() and swim(), inherited from two entirely separate base classes — something Java's single-inheritance model would require an interface for, but here both bases can carry real implementation.
class Flyable {
public:
void fly() { std::cout << "Flying\n"; }
};
class Swimmable {
public:
void swim() { std::cout << "Swimming\n"; }
};
class Duck : public Flyable, public Swimmable { // inherits from BOTH
};
Duck d;
d.fly(); // from Flyable
d.swim(); // from SwimmableThe diamond problem
Without virtual inheritance, D ends up with TWO separate, independent copies of A's data — one inherited via B, one via C — and d.value is genuinely ambiguous, since the compiler doesn't know which copy you mean.
class A {
public:
int value = 0;
};
class B : public A { }; // B has its OWN copy of A
class C : public A { }; // C has its OWN, SEPARATE copy of A
class D : public B, public C { }; // D ends up with TWO copies of A's value!
D d;
// d.value = 5; // COMPILE ERROR: ambiguous — which copy, via B or via C?
d.B::value = 5; // must disambiguate explicitlyvirtual inheritance: the fix
With virtual on both B's and C's inheritance from A, D ends up with exactly ONE shared copy of A — d.value is now unambiguous, resolving the diamond problem at its root.
class A {
public:
int value = 0;
};
class B : public virtual A { }; // virtual inheritance
class C : public virtual A { }; // both share ONE A
class D : public B, public C { };
D d;
d.value = 5; // no ambiguity now — there's genuinely only one A