Inheritance Access Levels
Part of the Object Oriented Programming section of Coddy's C++ journey — lesson 49 of 104.
The inheritance type you choose affects how base class members are accessed in the derived class. C++ offers three options: public, protected, and private inheritance.
Here's how each type transforms member access:
| Base Member | public inheritance | protected inheritance | private inheritance |
|---|---|---|---|
| public | public | protected | private |
| protected | protected | protected | private |
| private | inaccessible | inaccessible | inaccessible |
class Base {
public:
int pub;
protected:
int prot;
private:
int priv;
};
class PublicDerived : public Base {
// pub is public, prot is protected, priv is inaccessible
};
class ProtectedDerived : protected Base {
// pub is protected, prot is protected, priv is inaccessible
};
class PrivateDerived : private Base {
// pub is private, prot is private, priv is inaccessible
};Public inheritance models "is-a" relationships and is by far the most common. A Dog is an Animal, so external code can treat it as one.
Protected and private inheritance model "implemented-in-terms-of" relationships. They hide the base class interface from outside code, useful when you want to reuse implementation without exposing the inheritance relationship. With private inheritance, even further derived classes lose access to the original base members.
Challenge
EasyLet's explore how different inheritance types affect member accessibility by building a simple device hierarchy. You'll create a base Device class and three derived classes, each using a different inheritance type, to see firsthand how public, protected, and private inheritance transform member access.
You'll organize your code across two files:
Device.h: Define a baseDeviceclass with three members at different access levels:- A public
std::string model - A protected
int serialNumber - A private
int internalCode(set to 999 by default) - A public method
showModel()that prints:Model: <model>
Then create three derived classes that each inherit from
Deviceusing different inheritance types:PublicDeviceusing public inheritance — add a methoddisplaySerial()that prints:Serial: <serialNumber>ProtectedDeviceusing protected inheritance — add a methoddisplaySerial()that prints:Serial: <serialNumber>PrivateDeviceusing private inheritance — add a methoddisplaySerial()that prints:Serial: <serialNumber>
Each derived class should have a constructor that takes a model name and serial number, passing the model to the base class and setting the serial number.
- A public
main.cpp: Read two inputs (each on a separate line):- Model name (string)
- Serial number (integer)
Create one object of each derived type with the same input values. Then demonstrate the access differences:
For
PublicDevice:- Call
showModel()directly on the object (works because public inheritance keeps it public) - Access
modeldirectly and print:Direct model access: <model> - Call
displaySerial()
For
ProtectedDeviceandPrivateDevice:- Only call
displaySerial()(the inheritedshowModel()andmodelare no longer publicly accessible from outside)
Output format:
--- PublicDevice --- Model: <model> Direct model access: <model> Serial: <serial> --- ProtectedDevice --- Serial: <serial> --- PrivateDevice --- Serial: <serial>
For example, with inputs Laptop and 12345:
--- PublicDevice ---
Model: Laptop
Direct model access: Laptop
Serial: 12345
--- ProtectedDevice ---
Serial: 12345
--- PrivateDevice ---
Serial: 12345Notice how only PublicDevice allows external access to the inherited public members. The other inheritance types hide the base class interface from outside code, but the derived classes can still access protected members internally through their own methods.
Cheat sheet
C++ offers three inheritance types that control how base class members are accessed in derived classes:
| Base Member | public inheritance | protected inheritance | private inheritance |
|---|---|---|---|
| public | public | protected | private |
| protected | protected | protected | private |
| private | inaccessible | inaccessible | inaccessible |
class Base {
public:
int pub;
protected:
int prot;
private:
int priv;
};
class PublicDerived : public Base {
// pub is public, prot is protected, priv is inaccessible
};
class ProtectedDerived : protected Base {
// pub is protected, prot is protected, priv is inaccessible
};
class PrivateDerived : private Base {
// pub is private, prot is private, priv is inaccessible
};Public inheritance models "is-a" relationships and is the most common. External code can access public members of the base class through the derived class.
Protected and private inheritance model "implemented-in-terms-of" relationships. They hide the base class interface from outside code. With private inheritance, even further derived classes lose access to the original base members.
Try it yourself
#include <iostream>
#include <string>
#include "Device.h"
using namespace std;
int main() {
// Read input
string modelName;
int serialNum;
getline(cin, modelName);
cin >> serialNum;
// TODO: Create objects of each derived type with the input values
// PublicDevice pubDev(modelName, serialNum);
// ProtectedDevice protDev(modelName, serialNum);
// PrivateDevice privDev(modelName, serialNum);
// TODO: Demonstrate PublicDevice access
cout << "--- PublicDevice ---" << endl;
// - Call showModel() directly on the object
// - Access model directly and print: Direct model access: <model>
// - Call displaySerial()
// TODO: Demonstrate ProtectedDevice access
cout << "--- ProtectedDevice ---" << endl;
// - Only call displaySerial() (showModel and model are not publicly accessible)
// TODO: Demonstrate PrivateDevice access
cout << "--- PrivateDevice ---" << endl;
// - Only call displaySerial() (showModel and model are not publicly accessible)
return 0;
}
This lesson includes a short quiz. Start the lesson to answer it and track your progress.
All lessons in Object Oriented Programming
1Fundamentals of OOP
External FilesC++ Build & CompilationHeader Files & Source FilesNamespaces & ScopeIntroduction to OOP in C++Classes vs ObjectsThe 'this' PointerMethods (Member Functions)Attributes (Data Members)Ctors & Dtors BasicsRecap - Simple Calculator4Class Properties
Instance vs Static MembersGetters and SettersConst Member FunctionsMutable KeywordStatic Methods and VariablesFriend Functions & ClassesRecap - Bank Account Manager7Inheritance
Basic InheritanceInheritance Access LevelsCtor & Dtor Call OrderMethod OverridingVirtual Functions & VTableMultiple InheritanceVirtual InheritanceRecap - Employee Hierarchy2Memory Management
Stack vs Heap MemoryPointers and ReferencesDynamic Memory (new/delete)Smart Pointers in C++RAII in C++Recap - Dynamic Array Manager5Encapsulation
Access Specifiers in C++Access Specifiers In DepthInformation HidingStruct vs ClassNested & Inner ClassesRecap - Student Records System8Polymorphism
Compile vs Runtime PolymorphFunction OverloadingVirtual Functions RevisitedPure Virtual FunctionsAbstract ClassesInterface Design in C++Dynamic Casting & RTTIRecap - Shape Calculator3Constructors & Destructors
Default ConstructorParameterized ConstructorCopy ConstructorMove ConstructorConstructor Init ListsDelegating ConstructorsDestructor Deep DiveRule of Three / Five / ZeroRecap - String Class6Operator Overloading
Intro to Operator OverloadArithmetic Operator OverloadComparison Operator OverloadStream OperatorsAssignment Operator Overload[] and () Operator OverloadType Conversion OperatorsRecap - Matrix Class9Templates
Function TemplatesClass TemplatesTemplate SpecializationVariadic TemplatesSFINAE & Type Traits BasicsRecap - Generic Container