Effective C++ item 40: Use Multiple Inheritance Judiciously

Multiple inheritance is more complex than single inheritance. It can lead to new ambiguity issues and to the need for virtual inheritance. In the case of diamond inheritance

1
2
3
4
5
6
7
8
9
class File {
private:
int data;
};
class InputFile: public File { ... };
class OutputFile: public File { ... };
class IOFile: public InputFile,
public OutputFile
{ ... };

You need to think about if data should be replicated twice in IOFile class. By default, it will. They way to avoid the duplication is to use virtual inheritance.

1
2
3
4
5
6
7
8
9
class File {
private:
int data;
};
class InputFile: virtual public File { ... };
class OutputFile: virtual public File { ... };
class IOFile: public InputFile,
public OutputFile
{ ... };

This way, data will only be there once in IOFile class.

But virtual inheritance imposes costs in size, speed, and complexity of initialization and assignment. It’s most practical when virtual base classes have no data.

Multiple inheritance does have legitimate uses. One scenario involves combining public inheritance from an Interface class with private inheritance from a class that helps with implementation. Remember the meaning of public and private inheritance from item 32 and item 39. When you already have a well defined interface class and a implementation class, you can use multiple inheritance to get both the interface as well as implementation.

1
class NewObject: public ObjectInterface, private ObjectImplementation { ... };

Another good example of using multiple inheritance is when you use gtest. gtest requires you to inherit from ::testing::Test if you are using fixture. And if you have to inherit from another class? Multiple inheritance is the only option there.

Reference:
“Effective C++” Third Edition by Scott Meyers.