Start learning free

LESSON 180 OF 343 · OBJECT-ORIENTED PROGRAMMING

Access Specifiers in C++: public, private and protected

Lesson Read the full explanation

TL ; DR:

  • C++ has three access specifiers: public:, private:, and protected:. They appear as labels in the class body and apply to everything below them until the next label.


  • By default, members of a class are private (and members of a struct are public):

    class Dog {
    private:
        string name;          // hidden from outside
    public:
        Dog(string name) { this->name = name; }
        string getName() { return name; }
    };
    

  • Outside the class, rex.name is a compile error. Use rex.getName() instead.



Full lesson:

Access specifiers in C++ work like access modifiers in Java/C#, but with different syntax — they're section labels rather than per-member modifiers.


class BankAccount {
private:
    double balance;        // hidden

public:
    void deposit(double amount) {
        if (amount < 0) return;
        balance += amount;
    }
    double getBalance() { return balance; }
};

If balance were public, any client could just write account.balance = -1000; and corrupt the state.


Your task

The Dog class has its name member in a private: block. Add a string getName() member function under public: that returns name.

Dog's name: Rex
STEP 1 OF 2
    Ctrl + Enter to check

    C++ · OBJECT-ORIENTED PROGRAMMING

    Access Modifiers in C++, explained

    Why hide anything

    A class does not have to let every part of the program touch its data. Consider a bank account. If the balance is open to everyone, any code can write account.balance = -1000; and break the rules the class was meant to enforce. If the balance is hidden and can only change through a deposit function, that function can check the amount first. Hiding the data and exposing a small set of safe operations is called encapsulation.

    C++ controls this with access specifiers, sometimes called access modifiers.

    The three specifiers

    • public: members can be used from anywhere.
    • private: members can be used only by the class's own member functions.
    • protected: members can be used by the class's own member functions and by member functions of classes derived from it. The inheritance lesson comes later; until then, treat protected as private with an exception for children.

    C++ uses section labels, not a keyword on each member as Java and C# do. A label applies to every member after it, until the next label:

    class BankAccount {
    private:
        double balance = 0;      // hidden
    
    public:
        void deposit(double amount) {
            if (amount < 0) return;
            balance += amount;
        }
        double getBalance() { return balance; }
    };
    

    Code outside the class can call deposit and getBalance, but a statement such as account.balance = 100; is rejected at compile time. The check is made by the compiler, so a mistake never reaches a running program.

    Defaults: class and struct

    If you write no label, the default depends on the keyword you used:

    • In a class, members are private by default.
    • In a struct, members are public by default.

    That is the only difference between the two keywords. Programmers usually reach for struct for plain bundles of public data and class for types that protect their state. Writing the labels explicitly, even when they match the default, makes the intent clear.

    Getters

    When outside code needs to read a private member, the class provides a getter: a public member function that returns the value.

    class Dog {
    private:
        string name;
    public:
        Dog(string name) { this->name = name; }
        string getName() { return name; }
    };
    

    With Dog rex("Rex");, the expression rex.name is a compile error, since the member is private. GCC says 'std::string Dog::name' is private within this context. The call rex.getName() works, and it returns a copy of the string, so the caller can read the name but can't change the stored one through it.

    Notice that access control is per class, not per object. Inside a Dog member function, you may read the private name of another Dog too, for example other.name in a function that compares two dogs.

    The lesson's exercise

    The Dog class keeps name in a private: block and has a constructor in the public: block. mainFunction calls rex.getName(), but no such function exists yet. The steps are:

    1. Under public:, below the constructor, declare a member function that returns a string and is named getName.
    2. Make its body return name;. This works because getName is a member of Dog, so it may read the private member.

    The expected output is:

    Dog's name: Rex

    The solution in C++

    class Dog {
    private:
        string name;
    public:
        Dog(string name) { this->name = name; }
    
        string getName() {
            return name;
        }
    };
    
    class Solution {
    public:
        void mainFunction() {
            Dog rex("Rex");
            cout << "Dog's name: " << rex.getName() << endl;
        }
    };
    

    The return type string must match the member's type. A getter declared as void getName() would print or do something, but give back nothing to cout, which would not compile in this line. Also, the constructor must stay public, because mainFunction creates the object.

    Common mistakes

    • Putting getName under private:. The member is then just as unreachable as the data.
    • Making everything public to avoid the error. It compiles, but it gives up the protection that was the point of the lesson.
    • Forgetting that class defaults to private when you leave out all the labels, and then wondering why every member is inaccessible.
    • Forgetting a colon after a label: public without : is a syntax error.
    • Ending getName without a return. Flowing off the end of a non-void function is undefined behaviour in C++. Most compilers warn about it.
    • Leaving private data uninitialized. A private double balance; with no value holds garbage. The BankAccount above gives it a starting value with = 0.

    Key takeaways

    • C++ has public:, private: and protected:, written as labels that apply until the next label.
    • A class is private by default and a struct is public by default.
    • Keep data private and expose it through member functions, so the class controls how its state changes.
    • A getter returns the value of a private member without allowing outside code to assign to it.
    Keep going with C++About 340 step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free