Skip to Content
Course content

29: Multiple Inheritance

Click on the "Edit" button in the top corner of the screen to edit your slide content.

A few years ago, I was consulting for a team building a simulation engine for industrial robotics. They had a class for PhysicsEntity to handle collisions and mass, and another for NetworkEntity to handle telemetry synchronization. The lead dev had tried to avoid multiple inheritance by creating a massive "God Class" called BaseEntity that contained every possible property. The result was a nightmare; every single object in the simulation, even a static floor tile, was carrying around network buffers and synchronization locks it never used. When we finally refactored to multiple inheritance, the architecture finally mirrored the reality of the hardware: a robot is both a physical object and a networked device.

In C++, multiple inheritance lets a class derive from more than one base class. While some languages (like Java or C#) forbid this to avoid complexity, C++ gives you the tool—provided you know how to handle the baggage that comes with it. You'll find that it's most useful when you're implementing "mixins" or multiple interfaces, allowing a class to play several different roles in your system simultaneously.

Combining Behaviors through Multiple Base Classes

To implement multiple inheritance, you simply list your base classes separated by commas in the class declaration. It looks straightforward, but the real power comes when you use this to enforce different contracts. Imagine you're building a game where some objects need to be saved to a disk and others need to be printed to a debug log.

class ISerializable {
public:
    virtual std::string serialize() = 0;
    virtual ~ISerializable() = default;
};

class ILoggable {
public:
    virtual void logState() = 0;
    virtual ~ILoggable() = default;
};

// This class "is a" serializable object AND "is a" loggable object
class PlayerProfile : public ISerializable, public ILoggable {
    std::string username;
    int level;

public:
    std::string serialize() override {
        return username + ":" + std::to_string(level);
    }

    void logState() override {
        std::cout << "Player " << username << " is at level " << level << "\n";
    }
};

I generally advise using this pattern for interfaces (classes with pure virtual functions) rather than inheriting heavy implementation logic from multiple sources. It keeps your memory layout cleaner and prevents your classes from becoming an unmanageable web of dependencies.

The Diamond Problem and Virtual Inheritance

Here is where things get messy. If you have a base class A, and classes B and C both inherit from A, and then class D inherits from both B and C, you have a "diamond." The problem is that D now contains two separate copies of A. If A has a member variable called id, D has two ids—one via B and one via C. The compiler will scream at you for ambiguity the moment you try to access that variable.

The fix is virtual inheritance. By marking the inheritance as virtual, you tell C++ that you only ever want one instance of the base class to exist in the hierarchy, regardless of how many paths lead back to it.

class Entity {
public:
    int id;
};

// Use the virtual keyword here
class PhysicsObject : virtual public Entity {};
class NetworkObject : virtual public Entity {};

// Now, NetworkPhysicsObject only has ONE copy of 'id'
class NetworkPhysicsObject : public PhysicsObject, public NetworkObject {};

I'll be honest: virtual inheritance adds a slight overhead to member access because the compiler has to use a pointer (a virtual base pointer) to find the shared base object. In 99% of your applications, this performance hit is negligible, but it's something to keep in mind if you're writing a high-frequency trading loop or a tight physics kernel.




📋 Practical Task

Implementing a Multi-Functional Smart Home Device

You are designing a system for a smart home. You need to create a hierarchy where devices can have different capabilities. Some devices consume power, some can be controlled via a network, and some do both.

Your task:

  1. Create a base class Device with a std::string deviceName and a virtual destructor.
  2. Create a class PowerConsumer that inherits virtually from Device. Give it a method void reportPowerUsage()` that prints the power consumption (e.g., "Device [name] is using 15W").
  3. Create a class NetworkConnectable that inherits virtually from Device. Give it a method void ping()` that prints "Pinging [name]... Success!".
  4. Create a class SmartCamera that inherits from both PowerConsumer and NetworkConnectable.
  5. In main(), instantiate a SmartCamera, set its name, and call both reportPowerUsage() and ping().

Ensure that you use virtual inheritance so that SmartCamera only contains one instance of the deviceName member.

Rating
0 0

There are no comments for now.

to be the first to leave a comment.