Multiple Inheritence


Introduction

This post is about multiple inheritance in C++.

But I want to start by dispelling a myth: C# and Java have multiple inheritance too!  Yes,  in C# and Java you can only directly extend one concrete base class.  But in both languages you can implement as many interfaces as you want.  This limitation is designed to overcome some obstacles of the more flexible multiple-inheritance mechanism of C++.  But just because multiple inheritance in these C-derived languages is limited doesn’t mean it’s not existent.  As I will explain, multiple inheritance is important in object oriented design.

Advanced Aside: However, just because a class in any of these languages can extend one or more base classes, does not mean that it should.  Often composition is a better approach then inheritance.  This is especially true in situations where the derived class would need to hide or change the meaning of a function it is inheriting from a base class.  For example, in beginner software textbooks, the relationship between a shape and circles/squares is often used to demonstrate inheritance.  Simply put, a circle or square would seem to inherit from a shape.  But what if we were using a shape class developed by another programmer, who had already defined the shape class with a member function called GetLengthOfLargestSide().  Well, since circles don’t have sides, this method would be meaningless for circles.  So while it might be appropriate for a square class to inherit from this shape class, a circle class should not.

When Does Inheritance Make Sense?

  • Derived classes are going to exactly reuse previously defined methods in a concrete base class:  For instance, if we had two different classes, one for a square and one for a rectangle, rather then having to BOTH define a method to calculate area (length x height), they could inherit from a common, concrete base class that already implements this method once (such as a parallelogram class).
  • Polymorphism: another method requires passing a parameter of one of several types, but the exact type is not known until run-time.
  • Union of Features: This is the use case that requires the multiple inheritance mechanism of C++.  The limitations in modern managed languages like Java and C# prevent this feature of inheritance.  A union of features occurs when a base class inherits different properties from multiple parents.

For instance, here is a union of features:

class Mother
public:
     int MothersChromosomes() { return 23; }
     // ...
};

class Father
public:
     int FathersChromosomes() { return 23; }
     // ...
};

class Child : Mother, Father
public:
     int ChildsChromosomes() { return MothersChromosomes() + FathersChromosomes(); }
     // ...
};

Note in practice this is probably a lousy example of a proper use of inheritance.   Remember earlier I cautioned about using inheritance when the child (base class) needs to delete or hide something it inherits from its parents.  Well, in my example, it is unlikely the child class inherits both the male parts and female parts of its parents, so to speak, unless we are talking about slugs or snails….  so the child would need to arbitrarily hide (or =delete) on of these features..

Advanced Aside: Inheritance might make sense when derived classes share a common set of constant read-only fields to define “magic numbers”, such as the meaning of PI. But note that using this technique in interfaces may be considered a bad design decision, in part because it breaks the “is-a” paradigm for inheritance. In fact, for interfaces, using public constant fields works in Java, but not in C#. Specifically, in Java, interfaces may contain public static final variables. In C#, interfaces may not contain fields at all. Often a better choice in all languages (C++, C#, and Java) is to declare public static fields in concrete classes (such as the PI field in C#’s System.Math class) or to use enumerations.

The C++ Multiple Inheritance Super Happy Path:

When a C++ class inherits from multiple parents (or even multiple ancestors further up the inheritance hierarchy… e.g. grandparents), in which EVERY function is pure virtual and there are NO public or protected fields than the C++ programmer has nothing to worry about. This is essentially the equivalent of having multiple inheritance of interfaces in Java, C#, etc. Obviously this super happy path means forfeiting many of the benefits of inheritance (and multiple inheritance) so I am not suggesting this optimistic scenario is realistic.

Problem With Multiple Inheritance

Finally I get to the meat of my post. I will demonstrate the crux of the C++ multiple inheritance issue by example. You can imagine even more complex scenarios by extending this example (in particular, the clashes I am about to demonstrate could be higher up the inheritance hierarchy).

#include<string>

#include<iostream>
using namespace std;

class English
{
public:
     virtual string MyFavoriteColor() { return "blue"; }
};

class Japanese
{
public:
     virtual string MyFavoriteColor() { return "青"; }
};

class Woops : English, Japanese
{
public:
   void PrintFavoriteColor()
   {
      cout << MyFavoriteColor; // ERROR (ambiguous) -- is this English or Japanese?

   }
 };

Note, the proper way to fix this is to preface the class name and scope operator before the ambiguous call, e.g.:  

cout << Japanese::MyFavoriteColor;

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s