C++ Access Specifiers
Lesson outline
Introduction to Access Specifiers
Access specifiers in C++ determine how class members (data and functions) can be accessed from different parts of a program. They are a key feature for implementing encapsulation, which helps keep the internal details of a class hidden and only exposes what is necessary.
C++ provides three main access specifiers: public, private, and protected. Choosing the appropriate one helps ensure clarity, safety, and proper use of class interfaces.
Access Specifier Overview
| Specifier | Access From Inside Class | Access From Derived Class | Access From Outside Class |
|---|---|---|---|
| public | Yes | Yes | Yes |
| protected | Yes | Yes | No |
| private | Yes | No | No |
Public Members
Public members can be accessed from anywhere: inside the class, in derived classes, and from outside the class using an object.
They are commonly used for functions that form the public interface of a class and for constants that clients of the class should be able to use.
Private Members
Private members can only be accessed from within the class in which they are declared. They cannot be directly accessed from derived classes or external code.
They are typically used for implementation details and for protecting the internal state of an object from unintended modification.
Protected Members
Protected members are similar to private members but can also be accessed by derived classes.
Important nuance: a derived class can access a base class's protected member generally only through its own subobject (i.e., via *this or a further-derived object). It cannot use this access to reach the protected member of an arbitrary, unrelated Base object.
Default Access Levels
By default, members of a class are private, while members of a struct are public.
If you omit the access specifier, C++ uses the default rules depending on whether you declare a class or a struct.
Default inheritance access (separate from member access): class Derived : Base (no keyword) means private inheritance by default; struct Derived : Base means public inheritance by default.
Friendship (Access Bypass)
friend declarations grant access to private and protected members of a class to specific functions or entire classes. Friendship is not inherited and is not transitive.
Inheritance Access vs Member Access
Member access (public/protected/private on members) governs where a member can be named. Inheritance access (public/protected/private after the colon) controls how base-class members appear through the derived class interface to outside code. It does not affect what the derived class itself can use internally.
Summary when inheriting from a base: with public inheritance, base public stays public and base protected stays protected (base private is inaccessible). With protected inheritance, base public and protected both become protected. With private inheritance, base public and protected both become private. In all cases, base private remains inaccessible to the derived class.
| Inheritance Mode | Base public becomes | Base protected becomes | Base private |
|---|---|---|---|
| public | public | protected | inaccessible |
| protected | protected | protected | inaccessible |
| private | private | private | inaccessible |
Best Practices
- Prefer private data members to preserve encapsulation and reduce dependencies on internal implementation.
- Use public access for methods that form the external interface of a class.
- Use protected access only when derived classes truly need it; avoid overusing it to prevent tight coupling.
- For simple data structures,
structwith public members may be appropriate. - Be cautious when modifying access levels in base classes, as it can affect all derived classes.
- Prefer composition over private inheritance unless you intentionally want an "is-implemented-in-terms-of" relationship and control the derived interface.
Summary Table
| Specifier | Typical Use |
|---|---|
| public | Methods and constants forming the external interface. |
| protected | Members available to derived classes but hidden from outside code. |
| private | Internal data and helper functions, hidden from all external access. |