The blog post introduces how access specifiers work in C++.

Public & Private Access Specifiers
In a previous article, I briefly mentioned that the public
keyword we use when defining
attributes and methods is one of the access specifiers that allows them to be accessible
from outside the class. Thus, with public access specifiers, we could do the following:
class Class {
public:
string public_attr;
void public_print() {
cout << "Public Method" << endl;
};
};
int main () {
Class public;
public.public_attr = "Public";
cout << public.public_attr << endl; // => Public
public.public_print(); // => Public Method
return 0;
}
However, there are cases where we do not want to allow access from outside the class. For example, we may not want user passwords or encryption algorithms to be publicly available. In such scenarios, we can use private access specifiers.
class BankAccount {
public:
string name;
int set_password(string password) {
string encrypted = this -> encrypt(password);
this -> password = encrypted;
return 1;
};
private:
string password;
string encrypt(string password) {
// Encryption
};
};
int main () {
BankAccount user;
user.name = "TK";
user.password = "abcdefg"; // => Err
user.set_password("abcdefg");
user.encrypt("abcdefg"); // => Err
return 0;
};
The private access specifier hides internal attributes and methods from the outside, allowing us to implement encapsulation and separation of concerns. For example, when building a machine learning model, we might use private access specifiers for the model's weights and biases, as they should only be modified through training.
If the user wants access to the model's weights and biases, it should be done through a public getter function that formats them appropriately. When initializing them, a setter function should be used to initialize weights automatically, rather than relying on manual user initialization.
Protected Access Specifiers
When the BankAccount
class is inherited to create a child class like ABCBankAccount
for ABC Bank,
we cannot access the private attributes of BankAccount
.
class ABCBankAccount : public BankAccount {
public:
float balance;
ABCBankAccount(string name, string password) : name(name) {
string encrypted = this -> encrypt(password); // => Err
this -> password = encrypted; // => Err
balance = 0;
;}
};
This is because the private access specifier prevents any outsider, including the child class, from accessing its members. To allow the child class to access them while still preventing access from outside the class, we can use the protected access specifier.
class BankAccount {
public:
string name;
int set_password(string password) {
string encrypted = this -> encrypt(password);
this -> password = encrypted;
return 1;
};
protected:
string password;
string encrypt(string password) {
// Encryption
};
};
class ABCBankAccount : public BankAccount {
public:
float balance;
ABCBankAccount(string name, string password) : name(name) {
string encrypted = this -> encrypt(password); // => OK
this -> password = encrypted; // => OK
balance = 0;
;}
};
int main () {
ABCBankAccount user("TK", "abcdefg");
cout << user.password << endl; // => Err
user.encrypt("abcdefg"); // => Err
return 0;
}
Base Class Access Specifiers
When using class inheritance, you might have seen the public keyword being used like
class ABCBankAccount : public BankAccount
. The public
here is called a base class access specifier,
and it dictates how the attributes and methods from the base class are inherited by the child class.
Below is a table showing how member access levels change depending on the base class access specifiers:
Base Class Access Specifier | Base Class Public Member | Base Class Protected Member | Base Class Private Member |
---|---|---|---|
public | Public | Protected | Inaccessible |
protected | Protected | Protected | Inaccessible |
private | Private | Private | Inaccessible |
As we've seen, the private members of the base class are inaccessible to anyone, including the child class, regardless of the base class access specifier. However, the public and protected members' access depends on the base class access specifier.
When the base class access specifier is public
, the public and protected members of the base
class retain their access levels in the child class. When the base class access specifier is
either protected
or private
, all public and protected members of the base class are
downgraded to protected or private in the child class, respectively. (The default base class access specifier is private if it is not provided.)
Resources
- Portfolio Courses. 2022. Base Class Access Specifiers | C++ Tutorial. YouTube.
- Portfolio Courses. 2022. Protected Class Members | C++ Tutorial. YouTube.
- Portfolio Courses. 2022. Public And Private Access Specifiers | C++ Tutorial. YouTube.