C++ Hybrid Inheritance
In this page:
What is Hybrid Inheritance?
Hybrid inheritance combines two or more inheritance patterns in a single class hierarchy — for example, mixing hierarchical inheritance for a set of siblings with multiple inheritance where one of those siblings also draws from a second, unrelated base class.
Example: What is Hybrid Inheritance?
#include <iostream>
class Base {
public:
void show() { std::cout << "Base" << std::endl; }
};
class Sibling1 : public Base {};
class Sibling2 : public Base {};
class Combo : public Sibling1 {
public:
void extra() { std::cout << "Combo" << std::endl; }
};
int main() {
Combo c;
c.show();
c.extra();
return 0;
}
Login to try C/C++/Java/PHP code in the editor
The Diamond Problem Intro
The diamond problem can resurface inside hybrid hierarchies whenever a class ends up inheriting from two parents that themselves share a common grandparent, producing duplicate paths back to that shared ancestor and duplicate copies of its data.
Example: The Diamond Problem Intro
#include <iostream>
class Grandparent {
public:
int value = 1;
};
class ParentA : public Grandparent {};
class ParentB : public Grandparent {};
class Grandchild : public ParentA, public ParentB {};
int main() {
Grandchild g;
// g.value would fail to compile: ambiguous, two Grandparent copies
std::cout << g.ParentA::value << std::endl;
return 0;
}
Login to try C/C++/Java/PHP code in the editor
Resolving Ambiguity with Scope Resolution
Without virtual inheritance, you can still resolve ambiguity caused by a diamond by explicitly qualifying which inheritance path you mean using the scope resolution operator, telling the compiler exactly which parent's copy of a member you're referring to.
Example: Resolving Ambiguity with Scope Resolution
#include <iostream>
class Grandparent {
public:
int value = 5;
};
class ParentA : public Grandparent {};
class ParentB : public Grandparent {};
class Grandchild : public ParentA, public ParentB {};
int main() {
Grandchild g;
std::cout << g.ParentA::value << " " << g.ParentB::value << std::endl;
return 0;
}
Login to try C/C++/Java/PHP code in the editor
Simple Hybrid Flow
When a hybrid hierarchy's inheritance paths don't actually overlap into a diamond shape, the design stays clean and predictable, letting you freely combine inheritance styles to model genuinely complex real-world relationships between types.
Example: Simple Hybrid Flow
#include <iostream>
class Engine {
public:
void start() { std::cout << "Engine starts" << std::endl; }
};
class Wheels {
public:
void roll() { std::cout << "Wheels roll" << std::endl; }
};
class Car : public Engine, public Wheels {};
int main() {
Car car;
car.start();
car.roll();
return 0;
}
Login to try C/C++/Java/PHP code in the editor
Constructor Call Sequence
Constructor execution order in a hybrid hierarchy follows a strict, well-defined sequence, starting from the topmost base classes and working downward through every intermediate level before finally reaching the most-derived class's own constructor.
Example: Constructor Call Sequence
#include <iostream>
class Base1 {
public:
Base1() { std::cout << "Base1" << std::endl; }
};
class Base2 {
public:
Base2() { std::cout << "Base2" << std::endl; }
};
class Derived : public Base1, public Base2 {
public:
Derived() { std::cout << "Derived" << std::endl; }
};
int main() {
Derived d;
return 0;
}
Login to try C/C++/Java/PHP code in the editor
Chapter Quiz — Complete all 8 topics to unlock
0/8 topics done
Complete these topics first: