This is an advanced C++ topic so don’t get worried if it’s difficult right now. You’ll rarely need to use private inheritance. And protected inheritance is probably even more rare. Some of my programming books just say that this whole topic is “beyond the scope of this book”. I’ll do my best to explain this concept because that’s what this podcast is all about. You get to learn from my experience.
If you’re using C#, Java, or some other language that doesn’t support private inheritance, then you’ll have to write your code differently. But even then, understanding this will help you. Once you understand private inheritance, then protected inheritance really gives you the same ability that extends to other derived classes.
If you’re not familiar with this topic or research some online forums, you’ll likely wonder why you just can’t use composition. So instead of inheriting from some class that you don’t want to make that relationship public, you instead declare a member variable in your class of the other base class. This is called composition and will be the topic of another episode.
Effectively, private inheritance and protected inheritance give you a new type of relationship. Instead of the public IS-A relationship, you can think of this new relationship as an IS-IMPLEMENTED-AS relationship.
Inheriting gives you three main benefits that you don’t get with composition:
1. You can access public and protected members in the other class. You’re limited to just the public members with composition.
2. You can override methods in the other class. This is still inheritance even if it is private or protected.
3. You can take advantage of a special compiler optimization that only applies to inheritance. It’s called the empty base class optimization. You don’t get this benefit unless it really is a base class.
Listen to the full episode or read the full transcript below.
Even if you’re using C# or Java where the concepts of private inheritance and protected inheritance don’t exist, you can still benefit from understanding the general idea. You’ll just have to write your code differently in those languages. You’ll be a better programmer if you know about this. Many senior C# developers that I know would have no clue about this topic.
I went online to search for this topic and on the C# forums, a common reply is, “Why would you want such a thing? Just use composition instead.” Well, after listening to this episode, you’ll know why and I hope will have a better appreciation for C++. We’ll discuss composition in a future episode.
The ability to inherit privately or protected becomes an even richer ability when combined with multiple inheritance. We’re not going to get into multiple inheritance today. That will be the subject of the next episode. So stay tuned, you won’t want to miss that one.
I’ve already described public inheritance in episode 24 and this episode will build on that one. In that episode, I described an example that had a book class which was the base class for a physicalBook class and an audioBook class. But what if the book class was written to take advantage of yet another class called a document.
Here’s where you need to ask yourself, is a book a document? Even though they share some things in common, it doesn’t seem right to me that all books can be considered to be documents. So a direct is-a relationship with public inheritance is probably not a good idea. The best solution would probably be to refactor the common behavior and data into a new class and then make both the book and document classes derive from this new class. That would make book and document related but as siblings that share the same base class instead of one deriving from the other. Maybe we could call this new class something simple like, text.
But what if the document class is not fully under our control to refactor? Or maybe it’s just too risky of a change to take on at this time. What do you do then? You could contain the document class inside the book class. This is the approach that you would most likely have to take in C# of Java. But C++ gives you another option. You can make your book class inherit privately from the document class.
This prevents any code from being able to treat books as if they were documents. From any code outside of the book class, there is no relationship between books and documents. But from inside the book class, it’s a whole different story. The book class now has access to all the public and protected members of the document class and no longer has to implement them. This is good because it prevents code duplication.
Another benefit is that the book class can also benefit from method overriding. Maybe there’s a virtual method in the document class that the book class needs to change slightly. Because inheritance is involved, even if it is private, you have the ability to do this.
This is no longer a simple IS-A relationship. Think of it more like an IS-IMPLEMENTED-AS relationship. Only the book class knows how it’s implemented.
If you’re going to use this ability then keeping the implementation details wrapped up entirely within the book class is probably the best way to go. That way, when you do eventually decide to refactor the document class so that there’s a new text base class, then only the document and the book class need to be changed.
If however, you find that you need to expose this implementation to other classes that derive from book, then you can turn the private inheritance into protected inheritance. Protected inheritance will still hide the fact that the book class inherits from the document class but any class that derives from book will be aware of this and can make use of the document class too. It’s like telling a secret to just a few extra friends. Watch out. This can cause problems.
Because protected and private inheritance is still inheritance, you get all the benefits of inheritance. For example:
◦ 1. The book class can access public and protected members of the document class. If you only have the option to use composition like in C# or Java, then you’ll be limited to using only the public members.
◦ 2. The book class can override methods in the document class. You can’t do this at all with composition.
◦ 3. This may not always be important but when it is, then this point is critical. In an earlier episode, I mentioned that the smallest size any instance can be is one byte. Imagine if the class you’re considering inheriting from has no data members. then creating an instance of this so your class can contain or compose the instance will add extra memory that is essentially wasted. However, if the class is part of your class through inheritance, and it doesn’t matter if this is public, protected, or private, then the compiler can get rid of that extra byte by rolling it into whatever memory is needed by the derived type. This actually has a name. It’s called the empty base class optimization.