CONTENTS:
I. INTRODUCTION
II. C++ "THIS" EXAMPLE PROGRAM SOURCE CODE
III. THE COMPILER
IV. "THIS" IS NOT AN ORDINARY VARIABLE
V. OVERLOADING OPERATORS
VI. CLASS MEMBER FUNCTIONS
VII. STATIC MEMBER FUNCTIONS, FRIEND FUNCTIONS, AND GLOBAL FUNCTIONS
VIII. ENABLING CASCADED FUNCTION CALLSIX. LINKED-LIST MANIPULATION
X. SUMMARY
YOU WILL LEARN:
1. When the "this" pointer can be used.
2. Why the compiler implicitly passes the "this" pointer.
3. Why the "this" pointer is not an ordinary variable.
4. Why the "this" pointer is important to operator overloading.
5. Three things explicitly stated by a class member function’s declaration.
6. Three functions the "this" pointer can not be used with.
7. How the "this" pointer enables cascaded function calls.
8. How the "this" pointer is used with linked-list manipulation.
• I. INTRODUCTION
Welcome to the “C++ 'this' Pointer Tutorial.”
The following example program will be discussed in this tutorial:
II. C++ "THIS" POINTER EXAMPLE PROGRAM SOURCE CODE
//***********************************
//C++ THIS-> POINTER TUTORIAL
//***********************************
#ifndef CALC_ERROR_H
#define CALC_ERROR_H
#include <cstdlib>
#include <fstream>
#include <iomanip>
#include <iostream>
#include <sstream>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string>
using namespace std;
#endif
//CALC_ERROR_H
class C
{
public:
static int objectCount;
//Count of object in existence.
C( int a );
//Constructor.
C( const C & );
//Copy constructor.
void m_Test2( C &CO );
//Enables Cascaded Function Calls.
void ClearScreen() const;
//Clears the screen.
void Pause() const;
//Waits for user response.
void DisplayNumberExistingObjects( C &CO ) const;
//Displays number of existing objects.
void m_SetA( int a, string title );
//Displays proof of equality of statements.
int m_GetA();
//Provides access to data member.
void m_SizeOfFile();
//Computes and displays
//the size of the file.
C& m_Add( int a )
{
its_a += a; return *this;
}
//Inline add.
C& m_Subtract( int a )
{
its_a -= a;
return *this;
}
//Inline subtract.
C& m_Multiply( int a )
{
its_a *= a;
return *this;
}
//Inline multiply.
C& m_Divide( int a )
{
its_a /= a;
return *this;
}
//Inline divide.
~C();
//Destructor.
private:
int its_a;
};
//***********************************
//Constructor.
//***********************************
C::C( int a )
{
string title = "CONSTRUCTOR:";
m_SetA( a, title );
objectCount++;
}
//***********************************
//Copy constructor.
//***********************************
C::C( const C & )
{
objectCount++;
}
//***********************************
//SetA
//Three equivalent statements.
//***********************************
void C::m_SetA( int a, string title )
{
//It is legal, though unnecessary,
//to explicitly use this
//when referring to members of the class.
ClearScreen();
cout << " " << title;
if ( title == "TEST 1:" )
{
cout << " CO.m_SetA( 2, 'TEST 1:' );";
//?
}
cout << endl << endl;
cout << " its_a = a; = ";
its_a = a;
//These three statements
//are equivalent.
cout << m_GetA();
cout << endl << endl;
cout << " this->its_a = a; = ";
this->its_a = a;
//These three statements
//are equivalent.
cout << m_GetA();
cout << endl << endl;
cout << " (*this).its_a = a; = ";
(*this).its_a = a;
//These three statements
//are equivalent.
cout << m_GetA();
cout << endl << endl;
cout << " All three statements are equivalent. " << endl << endl;
Pause();
}
//***********************************
//GetA
//***********************************
int C::m_GetA()
{
return this->its_a;
}
//***********************************
//This function computes and displays
//the size of the file.
//***********************************
void C::m_SizeOfFile()
{
long begin;
//Instantiates begin as an object
//of class type long.
long end;
//Instantiates end as an object
//of class type long.
ifstream myfile ( "ExampleFile.dat" );
//Determine whether the stream
//object is currently associated
//with a file, if so, file is open.
begin = myfile.tellg();
//tellg(); is used to get the
//beggining position in the stream
myfile.seekg ( 0, ios::end );
//after it has been moved
//with seekg(); to the end of the stream;
//therefore, determining the size
//of the file.
end = myfile.tellg();
//tellg(); is used to get the ending
//position in the stream
myfile.close();
//closes file.
ClearScreen();
cout << " File size is: " << ( end - begin ) << " bytes." << endl;
//end - begin determines size
//of the file.
Pause();
}
//***********************************
//Test2,
//enabling cascaded function calls.
//***********************************
void C::m_Test2( C &CO )
//Passing an object to a function.
{
CO.ClearScreen();
cout << " Initial value of data member is " << CO.m_GetA() << endl << endl;
CO.m_Add( 2 );
cout << " Value of data member after addition of 2 is " << CO.m_GetA() << endl << endl;
CO.m_Subtract( 1 );
cout << " Value of data member after subtraction of 1 is " << CO.m_GetA() << endl << endl;
CO.m_Multiply( 10 );
cout << " Value of data member after multiplication by 10 is " << CO.m_GetA() << endl << endl;
CO.m_Divide( 5 );
cout << " Value of data member after division by 5 is " << CO.m_GetA() << endl;
CO.Pause();
CO.ClearScreen();
cout << endl << endl;
this->its_a = 2;
cout << " New initial value of data member is " << CO.m_GetA() << endl << endl;
CO.m_Add( 2 ).m_Subtract( 1 ).m_Multiply( 10 ).m_Divide( 5 );
cout << " After processing the following function" << endl << endl;
cout << " which enables a cascaded function call:" << endl << endl;
cout << endl << endl << " ";
cout << "CO.m_Add( 2 ).m_Subtract( 1 ).m_Multiply( 10 ).m_Divide( 5 );" << endl << endl;
cout << " Final cascaded value of data member is " << CO.m_GetA() << endl << endl;
cout << endl;
CO.Pause();
}
//***********************************
//Clear Screen.
//***********************************
void C::ClearScreen() const
{
system( "CLS" );
cout << endl << endl << endl;
}
//***********************************
//Pause.
//***********************************
void C::Pause() const
{
cout << endl << endl << endl;
cout << " ";
system( "PAUSE" );
}
//***********************************
//Computes and displays number of
//objects in existence.
//***********************************
void C::DisplayNumberExistingObjects( C &CO ) const
{
ClearScreen();
cout << endl << endl << endl;
cout << " Number of existing class C objects: ";
cout << C::objectCount;
Pause();
}
//***********************************
//Destructor
//***********************************
C::~C()
{
}
int C::objectCount = 0;
//Initialize static member of C class.
//***********************************
//MAIN() FUNCTION.
//***********************************
int main(int argc, char* argv[])
{
int choice = 0;
bool exitt = false;
//***********************************
C CO( 0 );
//Instantiate class member object
//CO of type C.
do
{
CO.ClearScreen();
cout << " C++ this-> Pointer Tutorial " << endl << endl;
cout << " ---------------------------------------------------" << endl << endl;
cout << " 0 Quit, exits program. " << endl << endl;
cout << " STEP 1a: Constructor equivalency. " << endl << endl;
cout << " 1 STEP 1b: Poof of equivalency: " << endl;
cout << " its_a = a; " << endl;
cout << " this->its_a = a; " << endl;
cout << " (*this).its_a = a; " << endl << endl;
cout << " 2 STEP 2: Proof enables cascaded function calls." << endl << endl;
cout << " 3 STEP 3: Displays number objects in existence. " << endl << endl;
cout << endl << endl;
cout << " Please type a number from 0 to 3 " << endl << endl;
cout << " then press Enter ==> ";
cin >> choice;
switch(choice)
//Start switch.
{
case (0):
exitt = true;
return EXIT_SUCCESS;
break;
case (1):
//***********************************
//Compute and display Test1.
//Initializing a data member.
//**********************************
{
CO.m_SetA( 2, "TEST 1:" );
}
//***********************************
break;
case (2):
//***********************************
//Compute and display Test2.
//***********************************
{
CO.m_Test2( CO );
//Passing an object to a function
//by reference.
}
//**********************************
break;
case (3):
//***********************************
//Compute and display number of
//objects in existence.
//***********************************
{
CO.DisplayNumberExistingObjects( CO );
}
//***********************************
break;
default:
CO.ClearScreen();
cout << " Switch default error message! ";
CO.Pause();
break;
}
//End switch.
}while( choice != 0 );
return EXIT_SUCCESS;
}
• III. THE COMPILER
The C++ keyword "this" is a special type of pointer. Most uses of the "this" pointer are implicit and most of the time you will not need to access it directly. You do not have to worry about creating or deleting the "this" pointer, it is created and deleted by the compiler.
Class member functions manipulate the correct class object data member because each object has its own address which is pointed to by its "this" pointer. The compiler makes the "this" pointer available as a local variable within the body of non-static member functions to point to the class object the class member function is working with.
The this pointer is passed by the compiler as an implicit hidden argument to each of the object’s non-static member functions when the member function is called. For example, in the attached example program, in the main() function we have the following function call:
CO.m_SetA( 2, "TEST 1:" );
This function’s declaration, definition, and call all show two parameters. The compiler works with the called function as if it were written with the following three arguments:
m_SetA(& CO, 2, "TEST 1:");
By this automatic internal conversion the compiler converts member function calls to add an argument which passes in the address of the class object.
The compiler has to maintain the same number of parameters in the function’s declaration, definition, and call. Therefore, the compiler also does an automatic internal conversion on the function’s declaration and definition by changing the function definition from:
//***********************************
//SetA
//Three equivalent statements.
//***********************************
void C::m_SetA( int a, string title )
{
//It is legal, though unnecessary,
//to explicitly use this
//when referring to members of the class.
ClearScreen();
cout << " " << title;
if ( title == "TEST 1:" )
{
cout << " CO.m_SetA( 2, 'TEST 1:' );";
}
cout << endl << endl;
cout << " its_a = a; = ";
its_a = a;
//These three statements
//are equivalent.
cout << m_GetA();
cout << endl << endl;
cout << " this->its_a = a; = ";
this->its_a = a;
//These three statements
//are equivalent.
cout << m_GetA();
cout << endl << endl;
cout << " (*this).its_a = a; = ";
(*this).its_a = a;
//These three statements
//are equivalent.
cout << m_GetA();
cout << endl << endl;
cout << " All three statements are equivalent. " << endl << endl;
Pause();
}
to:
void C::m_SetA( C* const this, int a , string title )
{
...
this->its_a = a;
...
}
The compiler has automatically converted the function’s declaration and definition by adding a new parameter. The added parameter is a hidden this pointer that points to the class object the class member function is working with.
The "this" pointer can be used implicitly by the compiler and explicitly by the programmer to access an object’s data members.
• IV. "THIS" IS NOT AN ORDINARY VARIABLE
The keyword "this" is a pointer to the object for which a nonstatic member function is invoked; however, "this" is not an ordinary variable:
A. It is not possible to take the address of "this."
B. It is not possible to declare "this."
C. It is not possible to assign to "this," it’s not an l-value; therefore, it can not be made null or zero.
D. It is not possible to modify "this." You can change the value of the object it points to; however, you can not make it point to something else. The "this" pointer is a const pointer.
E. An object's "this" pointer is not part of the object itself; therefore, the size of "this" is not included when computing the size of an object.
F. The "this" pointer is also used to guard against self-reference and to resolve ambiguity.
• V. OVERLOADING OPERATORS
The "this" pointer's type can be modified in the function declaration by the const and volatile keywords. To declare a function as having the attributes of one or more of these keywords, add the appropriate keywords after the function argument list. Examples are as follows:
In a member function of a class C, the type of "this" is C*.
The type of "this" if the member function is declared const, is const C*.
The type of "this" if the member function is declared volatile, is volatile C*.
The type of "this" If the member function is declared const volatile, is const volatile C*.
In a member function of a class C, the type of "this" is C*.
The type of "this" if the member function is declared const, is const C*.
The type of "this" if the member function is declared volatile, is volatile C*.
The type of "this" If the member function is declared const volatile, is const volatile C*.
The "this" pointer is very important when operators are overloaded. For example, when the binary operator+(), which takes only one parameter, is overloaded it is the object on the left that generates the call to the operator function. Member functions use the "this" pointer implicitly to obtain the left operand for binary operators. This was demonstrated in “The Compiler” section of this tutorial.
• VI. CLASS MEMBER FUNCTIONS
Member function declarations explicitly state the following:
A. The member function must be invoked on an object; which means the member function has a "this" pointer passed to it implicitly by the compiler.
B. The member function can access the private part of a class declaration.
C. The member function is in the scope of the class.
You can refer to the particular class object that a member function is called for by using the "this" pointer in the body of the member function.
The "this" pointer is very important whenever a member function must utilize a pointer to the object that invoked it. Each member function contains an implicit handle, in the form of a pointer represented by the C++ keyword "this," to the object on which it operates.
The object's address is available from within the member function as the "this" pointer. The expression "*this" is commonly used to return the current object from a member function.
Just a reminder, as shown in the example program, always declare all member functions that do not alter the class object for which they are called as const.
• VII. STATIC MEMBER FUNCTIONS, FRIEND FUNCTIONS, AND GLOBAL FUNCTIONS
The "this" pointer cannot be used with:
A. Static member functions.
A static member function is not passed a "this" pointer.
B. Friend functions.
Friend functions are not members of a class; therefore, they are not passed a "this" pointer.
C. Global functions.
Global functions are not passed a "this" pointer.
• VIII. ENABLING CASCADED FUNCTION CALLS
The "this" pointer can be used to enable cascaded function calls.
Cascaded function calls are function calls that invoke multiple functions in the same statement sequentially using left to right precedence so that the output of one function becomes the input of the next function.
//***********************************
//Test2,
//enabling cascaded function calls.
//***********************************
void C::m_Test2( C &CO )
//Passing an object to a function.
{
CO.ClearScreen();
cout << " Initial value of data member is " << CO.m_GetA() << endl << endl;
CO.m_Add( 2 );
cout << " Value of data member after addition of 2 is " << CO.m_GetA() << endl << endl;
CO.m_Subtract( 1 );
cout << " Value of data member after subtraction of 1 is " << CO.m_GetA() << endl << endl;
CO.m_Multiply( 10 );
cout << " Value of data member after multiplication by 10 is " << CO.m_GetA() << endl << endl;
CO.m_Divide( 5 );
cout << " Value of data member after division by 5 is " << CO.m_GetA() << endl;
CO.Pause();
CO.ClearScreen();
cout << endl << endl;
this->its_a = 2;
cout << " New initial value of data member is " << CO.m_GetA() << endl << endl;
CO.m_Add( 2 ).m_Subtract( 1 ).m_Multiply( 10 ).m_Divide( 5 );
cout << " After processing the following function" << endl << endl;
cout << " which enables a cascaded function call:" << endl << endl;
cout << endl << endl << " ";
cout << "CO.m_Add( 2 ).m_Subtract( 1 ).m_Multiply( 10 ).m_Divide( 5 );" << endl << endl;
cout << " Final cascaded value of data member is " << CO.m_GetA() << endl << endl;
cout << endl;
CO.Pause();
}
• IX. LINKED-LIST MANIPULATION
Linked-list manipulation is a common explicit use of the "this" pointer in the event code is necessary to first checks if the left and right operands of operator= are the same object.
• X. SUMMARY
As shown in the attached example program, using the class data member name is equivalent to using the class data member name with the "this" pointer and the -> class member access operator. You can explicitly use the keyword "this" pointer and the class member access operator -> when referring to data members of a class.
The "this" pointer is passed as an implicit argument by the compiler to each of a class’s non-static member functions. The "this" pointer provides the functions access to the correct object’s data members.
Each object has its own copy of data. When a member function is called the compiler has to be told by the programmer the class object and class member data the programmer wants the member function to use. The compiler in turn implicitly passes the "this" pointer to the member function when the member function is called to tell the member function the identity of the object whose data the member function will be working with.
Implicitly means with no programmer involvement. If the programmer adds the "this" pointer to the code then it is being stated explicitly by the programmer.
1. When the "this" pointer can be used.
2. Why the compiler implicitly passes the "this" pointer.
3. Why the "this" pointer is not an ordinary variable.
4. Why the "this" pointer is important to operator overloading.
5. Three things explicitly stated by a class member function’s declaration.
6. Three functions the "this" pointer can not be used with.
7. How the "this" pointer enables cascaded function calls.
8. How the "this" pointer is used with linked-list manipulation.
Elcric Otto Circle
-->
-->
How to Link to My Home Page
It will appear on your website as:"Link to ELCRIC OTTO CIRCLE's Home Page"
No comments:
Post a Comment