Accessing data members of a class depends upon the access specifiers of these members. Sometimes there is a necessity to provide access even to private data members. In this case technique of Accessors (getters) and Mutators (setters) are used.
We can use Person class from the previous topic to show how you can access data members with different access types:
class Person { public://access control string firstName;//these data members string lastName;//can be accessed tm dateOfBirth;//from anywhere protected: string phoneNumber;//these data members can be accessed inside this class, int salary;// by friend functions/classes and derived classes private: string address;//these members can be accessed inside the class unsigned long int insuranceNumber;//and by friend classes/functions };
The access to public data members can be done by using dot operator (arrow operator in the case of pointers):
Person person1;//declare a person //access public data members person1.firstName = "Smith";//set first name of person1 to Smith person1.lastName = "James";//set last name of person1 to James person1.dateOfBirth.tm_year = 1980;//set year of birth of person1 to 1980
In the case of pointer of a Person the access to public data members is done in the following way:
Person* person2 = new Person();//declare a person //access public data members person2->firstName = "Moore"; person2->lastName = "Daniel"; person2->dateOfBirth.tm_year = 1988;
Data members can also be used as below:
string pName = person1.firstName; cout << "First name " << pName << endl;
This code produces the following output:
First name Smith
The access to private data members outside of class is allowed only to friend classes or functions. But you can specify a special function Accessor to get the value of private data member. In this case a good style is to start name of this function with get, followed by the data member identifier. The return type must be the same as type of the data member. For example we can create 2 getter functions for address and insuranceNumber data members:
public: string getAddress() { return address; } long int getInsuranceNumber() { return insuranceNumber; }
Now we can use getters to access these private data members:
cout << "Person1 address: " << person1.getAddress();
Accessors are often used to perform some additional checks before returning a value. For example, we can check if the address is not an empty string before returning address value. This can avoid some of the errors in runtime:
string getAddress() { if (!address.empty()) return address; else return "Attention!!! Address is empty"; }
As you can see, string is a class too. We are calling its public member function empty () to determine if a string is empty.
Mutators (setters) are used to set values of private data members. One of the main goals of a mutator is to check correctness of the value to be set to data member. A setter’s name starts with set, followed by name of data member. Setter must have one parameter of the same type as the data member to bet set by the setter. Here is an example of creating setter for insurance number: we can check if a 9 digits number is passed to the setter and display an error message in the case is a wrong number:
public: void setInsuranceNumber(unsigned long int insurance) { if (insurance >= 100000000 && insurance <= 999999999) insuranceNumber = insurance;//a correct value is set else //display only error message and do not set incorrect value cout << "Incorect Insurance number" << endl; }
Sometimes you can use the return value of the setter to keep track if a value is set. We can modify the above example to work in the following way: the setter will return true if the correct value is set. Otherwise it will return false:
bool setInsuranceNumber(unsigned long int insurance) { if (insurance >= 100000000 && insurance <= 999999999) { insuranceNumber = insurance;//a correct value is set return true;//everything is ok } else //do not set incorrect value and return false return false; }
It can be used in the program to get a correct input from user:
unsigned long int iNum; cout << "Please, enter you Insurance Number:" << endl; cin >> iNum; //try to set the value bool result = person1.setInsuranceNumber(iNum); while (!result)//while result is not true { cout << "Enter a valid Insurance Number:" << endl; cin >> iNum; //try to set the value again result = person1.setInsuranceNumber(iNum); }
You can try to enter an incorrect value:
Please, enter you Insurance Number:
1234
Enter a valid Insurance Number:
032
Enter a valid Insurance Number:
123456789
Protected data members can be accessed in the same way as public data members from friend functions or classes and from derived classes. If you need to provide access to protected data members from any other functions, you will have to use the same technique as for accessing private data members.