Multiple Inheritance
Part of the Object Oriented Programming section of Coddy's C++ journey — lesson 53 of 104.
C++ allows a class to inherit from multiple base classes simultaneously. This is called multiple inheritance and lets you combine features from different class hierarchies.
To inherit from multiple classes, separate them with commas:
class Printer {
public:
void print() {
std::cout << "Printing document" << std::endl;
}
};
class Scanner {
public:
void scan() {
std::cout << "Scanning document" << std::endl;
}
};
class MultiFunctionDevice : public Printer, public Scanner {
public:
void copy() {
scan();
print();
}
};The MultiFunctionDevice class now has access to methods from both Printer and Scanner:
MultiFunctionDevice mfd;
mfd.print(); // From Printer
mfd.scan(); // From Scanner
mfd.copy(); // Its own methodConstructors are called in the order the base classes are listed in the inheritance declaration (left to right), and destructors in reverse order. You can pass arguments to each base constructor in the initialization list:
class MultiFunctionDevice : public Printer, public Scanner {
public:
MultiFunctionDevice() : Printer(), Scanner() {}
};A potential issue arises when both base classes have a member with the same name. This creates ambiguity, and you must use the scope resolution operator to specify which one you mean:
class A { public: void show() {} };
class B { public: void show() {} };
class C : public A, public B {};
C obj;
obj.A::show(); // Call A's version
obj.B::show(); // Call B's versionMultiple inheritance is powerful but can lead to complex situations, especially when base classes share a common ancestor. We'll explore that challenge in the next lesson.
Challenge
EasyLet's build a smart home device system that combines capabilities from multiple base classes using multiple inheritance. You'll create devices that can both connect to WiFi and be controlled by voice, then combine these features into a unified smart speaker.
You'll organize your code across three files:
WiFiDevice.h: Define aWiFiDeviceclass that represents any device capable of connecting to a network:- A protected
std::string networkNamemember - A constructor that takes a network name and stores it
- A public
connect()method that prints:Connecting to WiFi: <networkName> - A public
status()method that prints:WiFi Status: Connected
- A protected
VoiceControl.h: Define aVoiceControlclass that represents any device with voice capabilities:- A protected
std::string assistantNamemember - A constructor that takes an assistant name and stores it
- A public
listen()method that prints:<assistantName> is listening... - A public
status()method that prints:Voice Status: Active
- A protected
main.cpp: Read three inputs (each on a separate line):- Device name (string)
- WiFi network name (string)
- Voice assistant name (string)
Define a
SmartSpeakerclass that publicly inherits from bothWiFiDeviceandVoiceControl:- A private
std::string deviceNamemember - A constructor that takes all three parameters, passes the network name to
WiFiDeviceand the assistant name toVoiceControlusing the initialization list, and stores the device name - A
powerOn()method that prints:<deviceName> powering on..., then callsconnect()andlisten() - A
showAllStatus()method that prints the device name, then uses the scope resolution operator to call bothstatus()methods to resolve the ambiguity
Create a
SmartSpeakerobject with the input values. CallpowerOn(), print a blank line, then callshowAllStatus().
For example, with inputs Echo, HomeNetwork, and Alexa:
Echo powering on...
Connecting to WiFi: HomeNetwork
Alexa is listening...
Echo Status:
WiFi Status: Connected
Voice Status: ActiveThe showAllStatus() method should print the device name followed by " Status:" on one line, then call each base class's status() method using WiFiDevice::status() and VoiceControl::status() to avoid ambiguity since both base classes have a method with the same name.
Cheat sheet
C++ supports multiple inheritance, allowing a class to inherit from multiple base classes simultaneously:
class DerivedClass : public BaseClass1, public BaseClass2 {
// Class body
};The derived class has access to members from all base classes:
class Printer {
public:
void print() {
std::cout << "Printing document" << std::endl;
}
};
class Scanner {
public:
void scan() {
std::cout << "Scanning document" << std::endl;
}
};
class MultiFunctionDevice : public Printer, public Scanner {
public:
void copy() {
scan(); // From Scanner
print(); // From Printer
}
};Base class constructors are called in the order they appear in the inheritance list (left to right). Use the initialization list to pass arguments to each base constructor:
class MultiFunctionDevice : public Printer, public Scanner {
public:
MultiFunctionDevice() : Printer(), Scanner() {}
};When multiple base classes have members with the same name, use the scope resolution operator to resolve ambiguity:
class A { public: void show() {} };
class B { public: void show() {} };
class C : public A, public B {};
C obj;
obj.A::show(); // Call A's version
obj.B::show(); // Call B's versionTry it yourself
#include <iostream>
#include <string>
#include "WiFiDevice.h"
#include "VoiceControl.h"
using namespace std;
// TODO: Define SmartSpeaker class that publicly inherits from both WiFiDevice and VoiceControl
// - Private member: deviceName (string)
// - Constructor: takes deviceName, networkName, assistantName
// Use initialization list to pass networkName to WiFiDevice and assistantName to VoiceControl
// - powerOn() method: prints "<deviceName> powering on...", then calls connect() and listen()
// - showAllStatus() method: prints "<deviceName> Status:", then calls both status() methods
// using scope resolution (WiFiDevice::status() and VoiceControl::status())
class SmartSpeaker {
// TODO: Implement the SmartSpeaker class here
};
int main() {
string deviceName, networkName, assistantName;
getline(cin, deviceName);
getline(cin, networkName);
getline(cin, assistantName);
// TODO: Create a SmartSpeaker object with the input values
// TODO: Call powerOn()
// TODO: Print a blank line
// TODO: Call showAllStatus()
return 0;
}
This lesson includes a short quiz. Start the lesson to answer it and track your progress.
All lessons in Object Oriented Programming
1Fundamentals of OOP
External FilesC++ Build & CompilationHeader Files & Source FilesNamespaces & ScopeIntroduction to OOP in C++Classes vs ObjectsThe 'this' PointerMethods (Member Functions)Attributes (Data Members)Ctors & Dtors BasicsRecap - Simple Calculator4Class Properties
Instance vs Static MembersGetters and SettersConst Member FunctionsMutable KeywordStatic Methods and VariablesFriend Functions & ClassesRecap - Bank Account Manager7Inheritance
Basic InheritanceInheritance Access LevelsCtor & Dtor Call OrderMethod OverridingVirtual Functions & VTableMultiple InheritanceVirtual InheritanceRecap - Employee Hierarchy2Memory Management
Stack vs Heap MemoryPointers and ReferencesDynamic Memory (new/delete)Smart Pointers in C++RAII in C++Recap - Dynamic Array Manager5Encapsulation
Access Specifiers in C++Access Specifiers In DepthInformation HidingStruct vs ClassNested & Inner ClassesRecap - Student Records System8Polymorphism
Compile vs Runtime PolymorphFunction OverloadingVirtual Functions RevisitedPure Virtual FunctionsAbstract ClassesInterface Design in C++Dynamic Casting & RTTIRecap - Shape Calculator3Constructors & Destructors
Default ConstructorParameterized ConstructorCopy ConstructorMove ConstructorConstructor Init ListsDelegating ConstructorsDestructor Deep DiveRule of Three / Five / ZeroRecap - String Class6Operator Overloading
Intro to Operator OverloadArithmetic Operator OverloadComparison Operator OverloadStream OperatorsAssignment Operator Overload[] and () Operator OverloadType Conversion OperatorsRecap - Matrix Class9Templates
Function TemplatesClass TemplatesTemplate SpecializationVariadic TemplatesSFINAE & Type Traits BasicsRecap - Generic Container