Part C - Encapsulation

The Current Object

Describe a member function's access mechanisms
Access the current object from within a member function

"Each member function knows what object it was invoked for and can explicitly refer to it" (Stroustrup, 1997)

Member function Access | this | Summary | Exercises


A member function executes on one specific set of instance variables.  That set consists of the data members of the object on which the client has called the member function.  We refer to that object as the current object.  In other words, the current object is the region of memory that contains the data on which the member function is currently operating. 

This chapter describes the mechanisms by which a member function accesses the current object and information from the client concurrently and shows how to refer to the current object from within the member function. 


Member Function Access

A member function accesses external information through parameters and can return information through parameters and a return value.  A member function's parameters are of two distinct kinds:

  • explicit - communicate with the client code
  • implicit - communicate with the current object

member functions

Explicit parameters receive information from the client and may return information to the client.  They are explicitly defined in the function header.  Their lifetime is the period during which the member function controls execution.

Implicit parameters access the current object.  They bind the member function to the object on which it is currently called.  Their lifetime is the lifetime of the current object: it starts just before the constructor executes and ends just after the destructor executes. 

implicit and explicit parameters

The syntax of each call to a normal member function reflects this mechanism.  The name of the object on which the function is called represents its implicit parameters, while the arguments passed to the function initialize its explicit parameters.

Consider the following calls to the display() member function:

 // ...

 Student::Student(int n, const char* g) {
     no = n;
     strcpy(grade, g);
 }

 void Student::display() const {
     cout << no << ' ' << grade;
 }

 // ...

 int main ( ) {
     Student harry(1234, "ABACA"), josee(1235, "BBCDA"); 

     harry.display();
     cout << endl;
     josee.display();
     cout << endl;
 }
















 1234 ABACA

 1235 BBCDA


The display() member function first accesses harry through its implicit parameters and then josee through its implicit parameters. 

The constructor called on harry receives data in its explicit parameters and copies that data through its implicit parameters into the instance variables of its current object.  The constructor called on josee receives data in its explicit parameters and copies that data through its implicit parameters into the instance variables of its current object. 


this

The region of memory that the current object occupies contains all of the data stored in its instance variables.  The complete set of instance variables has its own address.  The keyword this returns that address.  The dereferenced keyword *this refers to the set of instance variables; that is, to the current object. 

For example, let us upgrade the display() member function to return a copy of the object upon which it has been called: 

 Student Student::display() const {

     cout << no << ' ' << grade;

     return *this;
 }
 int main() {
     Student harry(1234,"ABACA"), backup;

     backup = harry.display();
     cout << endl;
     backup.display();
     cout << endl;
 }









 1234 ABACA

 1234 ABACA


The keyword this is only accessible from within a member function. 

Reference to the Current Object

We can improve our definition of display() by returning an unmodifiable reference to the current object rather than a copy of the object.  This makes a difference if the object is large, since copying all of its instance variables would be computationally intensive.  Returning a reference only involves copying the object's address, which is typically a 4 byte operation: 

 const Student& Student::display() const { 

     cout << no << ' ' << grade;

     return *this;
 }

The const qualifier on the return type prohibits the client code from placing the call to the member function on the left side of an assignment operator. 

Assigning to the Current Object

To copy the set of instance variables of one object into the current object, we use the dereferenced keyword *this as the left operand in an assignment expression.

 *this =            ;

Localizing Constructor Logic

For example, we can localize all of the validation for a class within one constructor and use *this to invoke validation within the other constructors:

 // Localized Validation
 // localize.cpp

 #include <iostream>
 using namespace std;
 const int M = 13;

 class Student {
     int no;
     char grade[M+1];
 public:
     Student();
     Student(int);
     Student(int, const char*);
     void display() const;
 };

 Student::Student() {
    // safe empty state
    no = 0;
    grade[0] = '\0';
 }

 Student::Student(int n) {
    *this = Student(n, "");
 }

 Student::Student(int n, const char* g) {
     int i;
     bool valid = true; // assume valid input, check invalidity

     // validate client data
     if (n < 1)
         valid = false;
     else {
         for (i = 0; g[i] != '\0' && valid; i++)
             valid = g[i] >= 'A' && g[i] <= 'F' && g[i] != 'E';

     if (valid) {
         // accept client data
         no = n;
         for (i = 0; g[i] != '\0' && i < M; i++)
             grade[i] = g[i];
         grade[i] = '\0';  // set the last byte to the null byte 
     }
     else {
         // set to a safe empty state
         *this = Student();
     }
 }

 void Student::display() const {
     cout << no << ' ' << grade;
 }

 int main () {
     Student harry(1234,"ABACA"), josee(1235), empty;

     harry.display();
     cout << endl;
     josee.display();
     cout << endl;
     empty.display();
     cout << endl;
 }


























































 1234 ABACA 

 1235

 0


If we were to define the safe empty state in the validating constructor, we could also call that constructor from the no-argument constructor. 

Extracting Input Data

Let us introduce a member function called read() that

  • extracts data from standard input
  • stores that data in the current object only if the data is valid
  • leaves the current object unchanged if the data is invalid 

To avoid duplicating our validation logic, we

  • construct a local Student object with the input data using the two-argument constructor
  • check the student number to determine if the local object accepted the data
  • assign the local object to the current object only if the data is valid
 void Student::read() {

     int no;         // will hold the student number
     char grade[14]; // will hold the grades

     cout << "Enter student number : ";
     cin >> no;
     cin.ignore(); // remove newline character
     cout << "Enter student grades : ";
     cin.getline(grade, 14);

     // construct the local object
     Student temp(no, grade);
     // if data is valid student number is non-zero
     if (temp.no != 0)
         // copy the local object into the current object 
         *this = temp;
 }

Since the local object (temp) and the current object are instances of the same class, this member function can access each of the local object's instance variables directly.


Summary

  • the current object is the object upon which a member function is called
  • a member function's parameters consist of implicit and explicit parameters
  • a member function's explicit parameters receive information from the client
  • a member function's implicit parameters bind the function to the current object
  • the keyword this holds the address of the current object
  • *this refers to the current object itself
  • the keyword this has no meaning outside a member function

Exercises




Previous Reading  Previous: Classes Next: Classes and Resources   Next Reading


  Designed by Chris Szalwinski   Copying From This Site   
Logo
Creative Commons License