0
0
CppComparisonBeginner · 4 min read

Public vs Private vs Protected Inheritance in C++: Key Differences

In C++, 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.

AspectPublic InheritanceProtected InheritancePrivate Inheritance
Access to base class public members in derived classPublicProtectedPrivate
Access to base class protected members in derived classProtectedProtectedPrivate
Access to base class private members in derived classNot accessibleNot accessibleNot accessible
Derived class type is a subtype of base classYes (is-a relationship)NoNo
Base class members accessible to outside code via derived classYes, if publicNoNo
Typical use caseInterface inheritanceRestricted inheritanceImplementation 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.

cpp
#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;
}
Output
Base show() called Base protectedFunc() called
↔️

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.

cpp
#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;
}
Output
Base show() called Base protectedFunc() called
🎯

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.

Key Takeaways

Public inheritance models an "is-a" relationship and keeps base class public members accessible.
Protected inheritance hides base class public members as protected, limiting outside access.
Private inheritance hides all inherited members as private, restricting access outside the derived class.
Use public inheritance for interface sharing, protected for limited access, and private for implementation reuse.
Private inheritance does not establish a subtype relationship, unlike public inheritance.