C++ Access Specifiers

C++ access specifiers control where class members can be used. They help you decide which data and methods are available from outside the class and which should stay hidden inside it.

The three main access specifiers are public, private, and protected. They are an important part of writing classes that are safe and easy to use.

Public And Private Members

A public member can be accessed from outside the class through an object. A private member can only be accessed by methods inside the same class.

Most classes keep their data members private and provide public methods for controlled access. This prevents other code from placing an object into an invalid state.

Specifier Meaning
public Can be used from outside the class.
private Can be used only inside the class.
protected Can be used inside the class and by derived classes.

Example: Protecting Data

This example keeps balance private. Code in main cannot change it directly, so deposits and withdrawals must go through the class’s public methods.

#include <iostream>

class BankAccount {
private:
    double balance;

public:
    BankAccount(double startingBalance) {
        if (startingBalance >= 0) {
            balance = startingBalance;
        } else {
            balance = 0;
        }
    }

    void deposit(double amount) {
        if (amount > 0) {
            balance += amount;
        }
    }

    bool withdraw(double amount) {
        if (amount > 0 && amount <= balance) {
            balance -= amount;
            return true;
        }

        return false;
    }

    void printBalance() const {
        std::cout << "Balance: $" << balance << std::endl;
    }
};

int main(void) {
    BankAccount account(100.0);

    account.deposit(40.0);
    account.withdraw(25.0);
    account.printBalance();

    std::cout << std::boolalpha;
    std::cout << "Can withdraw 200? " << account.withdraw(200.0) << std::endl;
    account.printBalance();

    return 0;
}

Output:

Balance: $115
Can withdraw 200? false
Balance: $115

How The Example Works

The balance member is listed after private:, so only methods of BankAccount can read or change it directly. The constructor, deposit(), withdraw(), and printBalance() are listed after public:, so code outside the class can call them.

The class controls the rules for changing the balance. A deposit must be greater than zero. A withdrawal must be greater than zero and no larger than the current balance. When the program tries to withdraw 200.0, the method returns false and leaves the balance unchanged.

If main tried to write account.balance = -500;, the program would not compile because balance is private. That is useful: the compiler stops outside code from bypassing the rules.

Class Defaults

In a C++ class, members are private by default until an access specifier changes that. This is why beginner examples often write public: before members they want to access from main.

#include <iostream>

class Counter {
    int value;

public:
    Counter() {
        value = 0;
    }

    void addOne() {
        value++;
    }

    int getValue() const {
        return value;
    }
};

int main(void) {
    Counter clicks;

    clicks.addOne();
    clicks.addOne();

    std::cout << clicks.getValue() << std::endl;

    return 0;
}

Output:

2

Here, value appears before public:, so it is private by default. The object can still be used because the class provides public methods to update and read the value.

Protected Members

The protected specifier is mainly used with inheritance. A protected member is hidden from ordinary outside code, but it can be used by classes that inherit from the original class. For now, remember that private is stricter than protected, and public is the most open.

Common Mistakes

  • Trying to access a private member directly from main.
  • Forgetting that class members are private by default.
  • Making every data member public, which allows outside code to skip validation rules.
  • Using getters and setters without checking whether outside code really needs that access.

Takeaway: access specifiers let a class expose a clean public interface while keeping its internal data protected.