Introduction to C++ | Access Specifiers

Access Specifiers in Public Inheritance

In C++, access specifiers (public, protected, and private) determine the accessibility of members (variables and methods) in a class. In public inheritance, the way these access specifiers behave in the derived class depends on how they are defined in the base class.

Key Points

Access Rules in Public Inheritance

Base Class Member Access in Derived Class
Public Remains public in the derived class.
Protected Remains protected in the derived class.
Private Not directly accessible in the derived class.

Syntax

Public Inheritance Syntax


        class Base {
            public:
                int publicVar;
            protected:
                int protectedVar;
            private:
                int privateVar;
        };
        
        class Derived : public Base {
            public:
                void show() {
                    publicVar = 10;  // Accessible (remains public)
                    protectedVar = 20; // Accessible (remains protected)
                    // privateVar = 30; // Not accessible (private in Base)
                }
        };
                    

Example of Public Inheritance

Here is an example to demonstrate the behavior of access specifiers in public inheritance:

Code Example


        #include <iostream>
        using namespace std;
        
        class Base {
            public:
                int publicVar;
        
            protected:
                int protectedVar;
        
            private:
                int privateVar;
        
            public:
                Base() : publicVar(1), protectedVar(2), privateVar(3) {}
        
                void displayPrivateVar() {
                    cout << "Private Variable (accessed within Base): " << privateVar << endl;
                }
        };
        
        class Derived : public Base {
            public:
                void accessBaseMembers() {
                    cout << "Public Variable: " << publicVar << endl;
                    cout << "Protected Variable: " << protectedVar << endl;
                    // privateVar is not accessible
                }
        };
        
        int main() {
            Derived obj;
            obj.accessBaseMembers();
        
            // Accessing Base class public member through Derived object
            obj.publicVar = 42;
            cout << "Modified Public Variable: " << obj.publicVar << endl;
        
            // obj.protectedVar = 10; // Error: protected member
            // obj.privateVar = 10;   // Error: private member
        
            obj.displayPrivateVar(); // Accessing private member through Base class function
        
            return 0;
        }
                    

Output

Public Variable: 1
Protected Variable: 2
Modified Public Variable: 42
Private Variable (accessed within Base): 3

Explanation

In this example:

Key Takeaways

Understanding Private Inheritance

In C++, inheritance is a mechanism where a class (child or derived class) acquires properties and behaviors (methods) from another class (parent or base class). With private inheritance, all the public and protected members of the base class become private members of the derived class.

Key Characteristics of Private Inheritance

Syntax

Private Inheritance Syntax


        class Base {
            public:
                int publicVar;
        
            protected:
                int protectedVar;
        
            private:
                int privateVar;
        };
        
        class Derived : private Base {
            public:
                void show() {
                    publicVar = 10;       // Accessible as private in Derived
                    protectedVar = 20;    // Accessible as private in Derived
                    // privateVar = 30;    // Error: Not accessible
                }
        };
                    

Example of Private Inheritance

Below is an example demonstrating private inheritance and how access to base class members is affected:

Code Example


        #include <iostream>
        using namespace std;
        
        class Base {
            public:
                int publicVar;
        
                Base() : publicVar(0), protectedVar(0), privateVar(0) {}
        
            protected:
                int protectedVar;
        
            private:
                int privateVar; // Not accessible in the derived class
        };
        
        class Derived : private Base {
            public:
                void accessBaseMembers() {
                    publicVar = 5;        // Inherited as private
                    protectedVar = 10;    // Inherited as private
                    cout << "PublicVar: " << publicVar << endl;
                    cout << "ProtectedVar: " << protectedVar << endl;
                }
        };
        
        int main() {
            Derived d;
        
            d.accessBaseMembers();
            // d.publicVar = 10;       // Error: publicVar is private in Derived
            // d.protectedVar = 15;    // Error: protectedVar is private in Derived
        
            return 0;
        }
                    

Output

PublicVar: 5
ProtectedVar: 10

Effects of Private Inheritance

Comparison with Public and Protected Inheritance

Access Level Public Inheritance Protected Inheritance Private Inheritance
Base Class Public Members Public in Derived Protected in Derived Private in Derived
Base Class Protected Members Protected in Derived Protected in Derived Private in Derived
Base Class Private Members Not Inherited Not Inherited Not Inherited

When to Use Private Inheritance

Understanding Protected Inheritance

In C++, inheritance allows a derived class to acquire properties and behaviors of a base class. The type of inheritance (public, protected, or private) determines how the access specifiers (public, protected, and private) of the base class members are treated in the derived class. Here, we focus on protected inheritance.

What is Protected Inheritance?

When a class is derived using protected inheritance:

Syntax

Protected Inheritance Syntax


        class Base {
            // Members of the Base class
        };
        
        class Derived : protected Base {
            // Members of the Derived class
        };
                    

Understanding Access Changes

Base Class Member Access in Derived Class Access in Further Derived Class
Public Protected Protected
Protected Protected Protected
Private Not Accessible Not Accessible

Example of Protected Inheritance

Here’s an example demonstrating how members of a base class behave under protected inheritance:

Code Example


        #include <iostream>
        using namespace std;
        
        class Base {
            public:
                int publicData = 1;
            protected:
                int protectedData = 2;
            private:
                int privateData = 3;
        
            public:
                int getPrivateData() { return privateData; } // Accessor for private data
        };
        
        class Derived : protected Base {
            public:
                void display() {
                    cout << "Public data (now protected in Derived): " << publicData << endl;
                    cout << "Protected data: " << protectedData << endl;
                    cout << "Private data (via accessor): " << getPrivateData() << endl;
                }
        };
        
        class FurtherDerived : public Derived {
            public:
                void show() {
                    // publicData and protectedData are accessible as protected in this class
                    cout << "Accessing publicData (protected in Derived): " << publicData << endl;
                    cout << "Accessing protectedData: " << protectedData << endl;
                    // getPrivateData() is accessible because it is public in Base
                }
        };
        
        int main() {
            Derived d;
            d.display();
        
            FurtherDerived fd;
            fd.show();
        
            return 0;
        }
                    

Output

Public data (now protected in Derived): 1
Protected data: 2
Private data (via accessor): 3
Accessing publicData (protected in Derived): 1
Accessing protectedData: 2

Key Points to Remember

Pro Tip:

💡 Pro Tip

Use public inheritance when the derived class is a specialized version of the base class (i.e., follows the "is-a" relationship). Ensure you carefully manage access to protected and private members to maintain encapsulation.

Private inheritance is rarely used compared to public or protected inheritance. It is suitable for scenarios where you want to hide the "is-a" relationship while reusing the implementation of the base class. Consider using composition as an alternative if the "has-a" relationship fits better.

Use protected inheritance when the derived class represents a specialized version of the base class and access to the base class members should be restricted to the derived class hierarchy only. For example, it can be useful in frameworks and libraries where controlled inheritance is needed.