Last Updated: January 3, 2026
Understanding how access specifiers work in a hierarchical structure is crucial for building robust and maintainable C++ applications.
Whether you're designing a large software system or a simple class structure, knowing how to control access can make a significant difference in your code's usability and security.
In C++, access specifiers determine how members of a class can be accessed. The three main specifiers are:
Understanding these access levels is the foundation for managing access control effectively. When we introduce inheritance, these rules become even more nuanced.
When a class inherits from a base class, the access specifiers dictate how the members of the base class are accessible in the derived class. The inheritance type (public, protected, or private) changes the access level of base class members in the derived class.
In public inheritance, public and protected members of the base class remain public and protected, respectively, in the derived class. Private members remain inaccessible.
In this example, the Derived class can access pubVar and protVar but not privVar. This behavior is consistent and expected.
In protected inheritance, both public and protected members of the base class become protected in the derived class. Private members remain inaccessible.
Here, pubVar is no longer accessible outside of the Derived class or its subclasses. This type of inheritance is useful when you want to limit access to the base class members within the class hierarchy.
In private inheritance, both public and protected members of the base class become private in the derived class. This means they can only be accessed by members of the derived class.
Here, even though protVar was protected in Base, it is now private in Derived, making it inaccessible to any outside classes.
Multiple inheritance introduces additional complexity in access control. When a class inherits from more than one base class, the access level of members depends on the inheritance mode used for each base class.
In this example, Derived can access hello() from Base1 since it’s public, but it can only access greet() from Base2 as a protected member.
When two base classes have members with the same name, ambiguity arises. This is especially true when a derived class tries to access these members.
In the accessFunc method, calling func() directly causes a compile-time error due to ambiguity. Specifying which base class function you want to call resolves the issue.
Understanding and applying the right access control strategies can lead to cleaner and more maintainable code. Here are some best practices to consider:
Understanding access control in inheritance is vital in real-world applications, especially for libraries and frameworks. For instance: