Access Specifiers in C++

Key points

  • All the access specifiers are used/accessed within the class regardless of the inheritance.
  • Protected members can be accessed by the inherited class as well. 
  • Public members can be accessed by all.


Private members accessed within the same class whereas protected members can be accessed within the same class and inheriting class. 

There is a thumb rule : When in doubt, use protected.

A class defined with the keyword class has private access for its members and its base classes by default. A class defined with the keyword struct has public access for its members and its base classes by default. A union has public access for its members by default.

Public members are accessed anywhere. 

#include <iostream>
#include <string>

class Army                         // Class declaration
{
private:
    int number_suffix;             // Member Variable
    string key;

public:
    void enrollment(string name, int age)
    {key = name; number_suffix = age;}
    
    void retirement()             // Member Functions
    {cout << key << " is retiring" << endl;}
};

int main()
{
    Army a1, a2;                  // Object creation and Memory allocation

    a1.enrollment("Shirley", 31);
    a1.retirement();

    a2.enrollment("Vicky", 32);
    a2.retirement();
    return 0; 
}

Data Hiding

The data stored in number_suffix and key can't be accessed directly as these are private access specifiers. But, still if anyone wants to access these private member variables, they could access through the member functions. This is an additional layer of security, so the data will not be corrupted accidentally. 

This is one of the key feature which is called 'Data Hiding'.

Points to Remember

  • If you declare private member variables in the class, make sure to have the getter and setter functions for the private member variable of the class. 
  • Favor private members over protected members because if the implementation of the base class changes, the updates to the derived classes are necessary. 
  • If there is no inheritance chosen, C++ defaults to private inheritance. 
  • Public inheritance is the far most commonly used inheritance.  If you have certain reason, go for it. Otherwise always prefer public.
  • Static member variables should be accessed using ClassName whereas non-static members can be accessed using the object.
class Army                         // Class declaration
{
private:
    static int numberSuffix;     // Static member variable
    int armyCode;                // Non-static member variable
    string key;
public:
    void enrollment(static int numberSuffix, int armyCode);
};

Army::numberSuffix= 890;

Army amy;
amy.armyCode = 100;


void Army::enrollment(static int numberSuffix, int armyCode)
{
    Army::armyCode = 100; // error
    this->armyCode = 100; // fine - Non-static
    armyCode = 100; // fine

    numberSuffix = 890; // fine
    Army::numberSuffix = 890; // fine
}
If you have declared variables as private, make sure that they have the get() function as public to be called from derived classes. So that derived classes should be able to access it. 

We have private members in base class, but we can't use it. OOps. Also, these private members occupies space but we couldn't use it. So, we need other access control mechanisms. protected access specifiers comes as rescue here. 

If you are a direct descendent of the parent class, you can access the variables using protected.  I have posted an interesting post for protected, just read it here if you are eager.

Call the overriding method from parent

 #include <iostream>
using namespace std;

class Army                         // Class declaration
{
private:
    int numberSuffix_;     
    int armyCode_;                
    string name_;
public:
    Army(int armycode, int suffix, string name) : name_(name) {
         //cout << "Parent Class:: " << __func__ << endl;     
    }
   
    string getPatientName() { 
        //cout << "Army " << __func__ << endl;
        return name_; 
    }
};

class ArmyHospital : public Army {
private:
    string hospitalName_;
public:
    ArmyHospital(int armycode, int suffix, string name) : Army(armycode, suffix, name) {
       hospitalName_ = "Kashmir Hospital";
       //cout << "Derived Class: " << __func__ << endl;
    }

    string getPatientName() { 
        //cout << "ArmyHospital  " << __func__ << endl;
        hospitalName_.append(" Officer's name is " + Army::getPatientName());
        return hospitalName_; 
    }
};


int main() 
{
    Army officer(23, 11, "Shirley");
    cout << "The officer's Name is " << officer.getPatientName() << endl << endl;
    ArmyHospital hospy(23, 11, "Sivy");
    cout << "The Hopital's Name is " << hospy.getPatientName() << endl;
    cout << "===========================================" << endl << endl;

    Army* off = new Army(2,1, "Clara");
    cout << "Pointer: The 2nd officer's Name is " << off->getPatientName() << endl << endl;
    ArmyHospital* hos = new ArmyHospital(2, 110, "Rosy");
    cout << "Pointer: The Hospital's Name is " << hos->getPatientName() << endl << endl;
    cout << "===========================================" << endl << endl;

    return 0;
}


Output:
1
2
3
4
5
6
7
8
9
10
11
The officer's Name is Shirley

The Hopital's Name is Kashmir Hospital Officer's name is Sivy
===========================================

Pointer: The 2nd officer's Name is Clara

Pointer: The Hospital's Name is Kashmir Hospital Officer's name is Rosy

===========================================

This will work only if the class is parent. I jotted down the example without virtual, but you can have virtual and check the same. Read this post to learn virtual function.

References: My extra learning from Google throughout my Masters




Comments