You are on page 1of 23

MODULE 2

Concepts: this pointer, references, type conversion

THIS POINTER IN C++


To understand „this pointer‟, it is important to know how objects look at the functions and
data members of the class.

 Each object gets its own copy of the data members of the class to which it belongs
to.

 All access the same function definition that is present in the code segment.

Each object gets its own copy of data members and all objects share single copy of
member functions.

Question is if only one copy of each member function exists and is used by multiple
objects, how are the proper data members used.

The answer to the above problem is the compiler supplies an implicit pointer along with
functions called as „this‟.

The „this‟ pointer is passed as a hidden argument to all non-static member function calls
and is available as a local variable within the body of all non-static functions.

„this‟ pointer is a constant pointer that holds the memory address of the current object.

„this‟ pointer is not available in static member functions as static members functions can
be called without any object (with class name).

#include<iostream>
using namespace std;
{
private:
int x;
public:
void setX (int y)
{
this->x = y;
}
void print()
{
cout << "x = " << x << endl;
}
};

int main ()
{
Test obj;
int z = 20;
obj.setX(z);
obj.print ();
return 0;
}

Output: x=20
In the above program when the function setX() is called, an integer value is passed as an
explicit parameter but the compiler embeds the „this‟ pointer as the hidden argument to
the function and hence this pointer is used to set the values of data members of the object
inside the function.

One of the important applications of this pointer is to return to the object it points to. The
below program illustrate the same.

include<iostream>
using namespace std;

class Test
{
private:
int x;
int y;
public:
Test(int x = 0, int y = 0)// constructor with default values
{
this->x = x;
this->y = y;
}
Test &setX(int a)
{
x = a;
return *this;
}
Test &setY(int b)
{
y = b;
return *this;
}
void print( )
{
cout << "x = " << x << " y = " << y << endl; }
};

int main()
{
Test obj1(5, 5);
obj1.setX (10).
obj1.setY(20);
obj1.print();
return 0;
}

Output: x=10 y=10

REFERENCES
C++contains a feature that is related to the pointer called reference.

Definition:

A reference is a name that acts as an alias, or an alternate name for previously defined
variable.

The main use of the reference variable is a formal argument to the function.

References provide a convenient alternative to pointers for processing large structures


with a function and they are essential for designing classes.

CREATING A REFERENCE
„&‟ symbol is used for obtaining the address of a variable. C++assigns an additional
meaning to the & symbol and is used for declaring references.

#include<iostream>

#include<iomanip>

using namespace std;

int main()

int i=10;

int &j=i;

cout<<"i="<<i<<"\t"<<"j="<<j;

j=20;

cout<<endl<<"i="<<i<<"\t"<<"j="<<j;

i=30;

cout<<endl<<"i="<<i<<"\t"<<"j="<<j;

cout<<endl<<"address of i="<<&i<<endl<<"addressof j="<<&j;

return 0;

Output:

i=10 j=10

i=20 j=20

i=30 j=30

address of i=0x7ffccbbff28c
addressof j=0x7ffccbbff28c

C++ provides 2 ways to achieve call by reference parameter passing

1. Explicitly pass a pointer to the argument


2. Passing a reference argument

The following program manually creates a call by reference parameter using a pointer in
the function called neg() which reverses the sign of the integer variable pointed by its
argument.

#include<iostream>

#include<iomanip>

using namespace std;

void neg(int *);

int main()

int x=10;

cout<<x<<"\t"<<"negated is"<<"\t";

neg(&x);

cout<<x<<endl;

return 0;

void neg(int *i)

*i=- *i;

}
OUTPUT:

10 negated is -10

neg() takes pointer to integer as a parameter.neg() must be explicitly called with the
address of x.

Further inside neg() the * operator must be used to access the variable pointed by i. This
is how call by reference in c++ is generated using c subset.

In c++ this process can be automated by using reference parameter.

#include<iostream>

#include<iomanip>

using namespace std;

void neg(int &i);

int main()

int x=10;

cout<<x<<"\t"<<"negated is"<<"\t";

neg(x);

cout<<x<<endl;

return 0;

void neg(int &i)

i=-i;
}

OUTPUT:

10 negated is -10

A few points to remember about reference

 .A reference must always be initialized when it is declared unlike pointer which


can be initialized later.

int i=4;

int &j; //error

j=i;

 A reference is rather like a constant pointer. Once a reference variable has been
defined to refer to a particular variable, it cannot refer to any other variable.

 When a variable pledges its alliance to a particular variable, it sticks to its pledge.

int &j=i; is equal to int *const ptr=&i;

A programming example to illustrate the alliance of a reference variable

#include <iostream>

using namespace std;

int main()

int i=10;

int &j=i;

cout<<"i="<<i;

cout<<",j="<<j<<endl;
cout<<"i's address="<<&i;

cout<<",j's addess="<<&j<<endl;

int k=20;

j=k;

cout<<"k="<<k;

cout<<",j="<<j;

cout<<",i="<<i<<endl;

cout<<"k address="<<&k;

cout<<", j address="<<&j<<endl;

return 0;

output :

i=10,j=10

i's address=0x7ffe59baf4d8,j's addess=0x7ffe59baf4d8

k=20,j=20,i=20

k address=0x7ffe59baf4dc, j address=0x7ffe59baf4d8

NOTE: A reference can be created only by initializing the declaration not by assignment.

 Like a reference to an int or a float or a char, a reference to a pointer can be


created.

int x=101;

int *y=&x;

int &z=*y;
int w=50;

y=&w;

 A variable can have multiple references, changing the value of one of them affects
the change in all others.

 Though an array of pointers is acceptable, an array of reference is not.

PASSING REFERENCES TO OBJECTS

When an object is passed as an argument to the function, a copy of the object is made.
When the function terminates the copy‟s destructor is called.

However when the object is passed by reference, no copy of the object is made meaning
no object used as a parameter is destroyed when the function terminates.

#include <iostream>

using namespace std;

class c1

int id;

public:

int i;

c1(int i);

~c1();

void neg(c1 &o)

o.i=-o.i;
}

};

c1::c1(int num)

cout<<"constructing"<<"\t"<<num<<endl;

id=num;

c1::~c1()

cout<<"destructing"<<"\t"<<id<<endl;

int main()

c1 x(10);

x.neg(x);

cout<<"End of program and no destructor called"<<endl;

return 0;

OUTPUT:

constructing 10

End of program and no destructor called


destructing 10

RETURNING REFERNCES

Functions can return references but it can be dangerous. When returning a reference to a
variable declared in the called function, the variable should be declared static within that
function or it must be a global variable.

Otherwise, the reference refers to an automatic variable that is discarded when the
function terminates, such a variable is said to be undefined and the programs behavior is
unpredictable.

References to undefined variables are called Dangling references.

#include< iostream>

using namespace std;

int num;

int &test()

int main()

test()= 5;

cout<<num;

return 0;

int &test()

return num;

}
In the program, the return type of function test() is int &. Hence this function returns a
reference of the variable num.

In the above program the return statement is return num. Unlike return by value this
statement does not return the value of num, instead it returns the variable itself (address).

So when the variable is returned, it can be assigned a value as done in

test()= 5;

 Ordinary function returns a value, but this function doesn‟t. Hence a constant
cannot be returned from this function.

 Cannot return a local variable from this function.

Difference between a pointer and a reference

 Reassignment: A pointer can be re-assigned. This property is useful for


implementation of data structures like linked list, tree, etc.

On the other hand, a reference cannot be re-assigned, and must be assigned at


initialization.

 Memory Address: A pointer has its own memory address and size on the stack
whereas a reference shares the same memory address (with the original variable).

Pointer is an independent variable and can be assigned NEW address values;


whereas a reference, once assigned, can never refer to any new object until the
variable goes out of scope.
 NULL value: Pointer can be assigned NULL directly, whereas reference cannot.

 Arithmetic operations: Various arithmetic operations can be performed on


pointers whereas there is no such thing called Reference Arithmetic.

 Indirection: You can have pointers to pointers to pointers offering extra levels of
indirection. Whereas references only offer one level of indirection.

TYPE CONVERSIONS IN C++


It is the process of converting one type into another. In other words converting an
expression of a given type into another is called type casting/type conversion.
TYPES OF CONVERSION
1. Basic data type to another basic data type

2. Basic type to class type

3. Class type to Basic type

4. Class type to another class type

BASIC DATA TYPE TO ANOTHER BASIC DATA TYPE


There are mainly two types of basic type to another basic data type conversions.

1. IMPLICIT CONVERSION

2. EXPLICIT CONVERSION

IMPLICIT CONVERSION:
It is the conversion done automatically by the compiler. It is also called as automatic
conversion.

An assignment operation (=) also causes the automatic type conversion. The type of data
to the right of an assignment operator is automatically converted to the type of the
variable on the left.

In expressions, when there are mixed data types the compiler converts them to the largest
data type that is present in the expression.

A program to illustrate automatic/implicit type conversion


#include <iostream>
using namespace std;
int main()
{
float x=3.14159;
int m;
double y=2.345679,z;
m=x;
z=x+m+y;
cout<<”m=”<<m<<endl;
cout<<”z=”<<z<<endl;
return 0;
}
Output:
m=3
z=8.48727

Program notes:
In the above program four variables of type float int double are declared respectively.
In the statement m=x where m is of type int and x is of type float, the assignment
operator causes the implicit conversion and thus the fractional part is truncated and only
integer value is assigned to m i.e,3.
In the next statement it is a expression containing mixed data types
z=x+m+y;
x is of type float, y is of type double, m is of type int. First the expression is evaluated by
converting them to the largest data type in this case it is double and the value is assigned
to another variable z by an assignment operator. Since both the types match (left side
variable type and right side expression type of an assignment operator) the evaluated
value is assigned to z. if the types do not match then the data type on the right of the
assignment operator is converted to the data type of the left side of the assignment
operator.
EXPLICIT TYPE CONVERSION
In explicit type conversion the programmer explicitly specifies or forces the expression to
be of specific type.
Ex: int x;
double y;
(float)(x+y/2);
In the above example x and y will be converted to float irrespective of their data types.

Drawbacks:
 The main disadvantage with implicit and explicit type conversion is the data loss.
The result will be an approximate value and the accurate one due to data loss.

BASIC TO CLASS TYPE CONVERSION


The source type is the basic type and the destination type is a class. Meaning a basic type
is converted to a class type.
Conversion from basic type to class type can be performed by using constructors.
Class employee
{
//class body
}
int main()
{
int Ecode=457;
employee emp;
emp=Ecode;
}
Here the assignment will be done by converting Ecode which is of basic or primary data
type into a class type.
A program to illustrate conversion from basic data type to class type using
constructor.
#include<iostream>
using namespace std;
Class Time
{
int hrs,min;
public:
Time(int);
Void display();
};
Time:: Time(int t)
{
cout<<” basic type to class type conversion “<<endl;
hrs=t/60;
min=t%60;
}
void Time:: display()
{
cout<<hrs<<endl;
cout<<min<<endl;
}
int main()
{
int duration;
cout<<”Enter the duration in minutes”
cin>>duration;
Time t1=duration;
t1.display();
}
In the above program an object of class Time is created and is assigned an integer
variable duration. When that is encountered the constructor is called to perform the type
conversion.
NOTE:
During type conversion using constructor only one argument can be passed as an
argument at a time and only at the time of initialization to do the type conversion.
In the above example left hand side of = operator is of class type and therefore type
conversion can be performed through operator overloading.

CLASS TYPE TO BASIC TYPE


In this type of conversion the source type is the class type and the destination type is the
basic type.
The constructor function do not support this conversion. Hence user must define their
own conversion function called as casting operator function.
General syntax:
Operator typename()
{
return (typename);
}
This function converts a class type to typename.
Example: operator double (): converts a class object to type double.
Operator int () : converts a class type to int
The casting operator function should satisfy the following conditions
1. It must be a class member.
2. It must not specify any return type.
3. It must not have any arguments.
Since the conversion function is a member function of a class it is invoked by the object
and therefore the values used for conversion inside the function belong to the object that
invoked the function. This means that the function does not need an argument.
A program to illustrate class type to basic type conversion
#include <iostream>
#include <iomanip>
using namespace std;
class Time
{
int hrs,min;
public:
Time(int ,int); // constructor
operator int(); // casting operator function
~Time() // destructor
{
cout<<endl<<"Destructor called..."<<endl;
}
};
Time::Time(int a,int b)
{
cout<<"Constructor called with two parameters..."<<endl;
hrs=a;
min=b;
}

Time :: operator int()


{
cout<<"Class Type to Basic Type Conversion..."<<endl;
return(hrs*60+min);
}
int main()
{
int h,m,duration;
cout<<"Enter Hours ";
cin>>h;
cout<<"Enter Minutes ";
cin>>m;
Time t (h, m); // construct object
duration = t; // casting conversion OR duration = (int) t
cout<<"Total Minutes are "<<duration;
return 0;
}
Output:
Enter Hours 2
Enter Minutes 75
Constructor called with two parameters...
Class Type to Basic Type Conversion...
Total Minutes are 195
Destructor called...

Program Notes:
The class Time has one object ‘t’ and suppose the total time of object ‘t’ is to be
assigned to any integer variable say ‘duration’ then the program above is the example of
the conversion from class to basic type. Here t is the object of type Time and duration is
of basic data type int. The assignment is done by converting„t‟ object which is of class
type to basic data type.
ONE CLASS TYPE TO ANOTHER CLASS TYPE

In this type of conversion both the type that is source type and the destination type are of
class type. Means the source type is of class type and the destination type is also of the
class type. In other words, one class data type is converted to another class type.

obj X=obj Y;

The class Y type is converted to class X and the converted value is assigned to obj X.
Since conversion takes place from class Y to class X, Y is known as the source class and
X is the destination class.

Conversion from one class to another class can be performed either by using

1. constructor
2. type conversion function.

The type of conversion to be used depends upon where the function is to be located.

1. Using cast operator function in source class


2. Using constructor conversion in destination class.

A program to illustrate type conversion from one class type to another class type

#include <iostream>

using namespace std;

class Kilometers

private:

double kilometers;

public:

Kilometers(double kilometers):kilometers(kilometers) {}
void display()

cout << kilometers << " kilometeres";

double getValue()

return kilometers;

};

class Miles

private:

double miles;

public:

Miles(double miles) : miles(miles) {}

void display()

cout << miles << " miles";

operator Kilometers()
{

return Kilometers(miles*1.609344);

Miles(Kilometers kilometers)

miles = kilometers.getValue()/1.609344;

};

int main(void)

/*

* Converting using the conversion function

*/

Miles m1 = 100;

Kilometers k1 = m1;

m1.display();

cout << " = ";

k1.display();

cout << endl;

/*
* Converting using the constructor

*/

Kilometers k2 = 100;

Miles m2 = k2; // same as: Miles m2 = Miles(k2);

k2.display();

cout << " = ";

m2.display();

cout << endl;

Output:

100 miles = 160.934 kilometers

100 kilometers = 62.1371 miles

Care should be taken to ensure that only one of these techniques is used on the pair of
classes.

If both are used together, the compiler throws an ambiguity error when the objects of the
two classes are equated.

You might also like