Public vs Private vs Protected Inheritance in C++: Key Differences
public inheritance keeps the base class's public and protected members accessible as public and protected in the derived class. protected inheritance makes them protected in the derived class, while private inheritance makes all inherited members private, restricting access outside the derived class.Quick Comparison
This table summarizes how public, protected, and private inheritance affect member access and inheritance type.
| Aspect | Public Inheritance | Protected Inheritance | Private Inheritance |
|---|---|---|---|
Access to base class public members in derived class | Public | Protected | Private |
Access to base class protected members in derived class | Protected | Protected | Private |
Access to base class private members in derived class | Not accessible | Not accessible | Not accessible |
| Derived class type is a subtype of base class | Yes (is-a relationship) | No | No |
| Base class members accessible to outside code via derived class | Yes, if public | No | No |
| Typical use case | Interface inheritance | Restricted inheritance | Implementation inheritance |
Key Differences
Public inheritance models an "is-a" relationship. The derived class publicly exposes the base class's public members, so outside code can use the derived object as if it were a base object. Protected members remain protected, accessible only inside the derived class or its children.
Protected inheritance hides the base class's public members from outside code by making them protected in the derived class. This means only the derived class and its subclasses can access those members, but outside code cannot. It restricts the interface but still allows inheritance.
Private inheritance hides all inherited members (public and protected) as private in the derived class. This means outside code and subclasses cannot access base class members through the derived class. Private inheritance models a "implemented-in-terms-of" relationship rather than "is-a". It is often used to reuse code without exposing the base class interface.
Code Comparison
This example shows public inheritance where the derived class exposes the base class's public method.
#include <iostream> class Base { public: void show() { std::cout << "Base show() called\n"; } protected: void protectedFunc() { std::cout << "Base protectedFunc() called\n"; } private: void privateFunc() { std::cout << "Base privateFunc() called\n"; } }; class Derived : public Base { public: void callProtected() { protectedFunc(); } }; int main() { Derived d; d.show(); // Accessible because of public inheritance d.callProtected(); // Accessing protected member via derived // d.protectedFunc(); // Error: protectedFunc is protected // d.privateFunc(); // Error: privateFunc is not accessible return 0; }
Private Inheritance Equivalent
This example shows private inheritance where the base class's public and protected members become private in the derived class, restricting outside access.
#include <iostream> class Base { public: void show() { std::cout << "Base show() called\n"; } protected: void protectedFunc() { std::cout << "Base protectedFunc() called\n"; } private: void privateFunc() { std::cout << "Base privateFunc() called\n"; } }; class Derived : private Base { public: void callShow() { show(); } // Allowed: Derived can access base public members void callProtected() { protectedFunc(); } // Allowed: Derived can access base protected members }; int main() { Derived d; d.callShow(); // Works d.callProtected(); // Works // d.show(); // Error: show is private in Derived return 0; }
When to Use Which
Choose public inheritance when you want to model a clear "is-a" relationship and allow users of the derived class to use base class features directly.
Choose protected inheritance when you want to inherit implementation but restrict access to base class members from outside code, allowing only derived classes to access them.
Choose private inheritance when you want to reuse base class implementation internally without exposing its interface, effectively hiding the base class from users of the derived class.