Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                

Pointer Declaration Syntax: Unit 4

Download as docx, pdf, or txt
Download as docx, pdf, or txt
You are on page 1of 24

Unit 4

What are Pointers?


In C++, a pointer refers to a variable that holds the address of another variable. Like
regular variables, pointers have a data type. For example, a pointer of type integer
can hold the address of a variable of type integer. A pointer of character type can
hold the address of a variable of character type.
You should see a pointer as a symbolic representation of a memory address. With
pointers, programs can simulate call-by-reference. They can also create and
manipulate dynamic data structures. In C++, a pointer variable refers to a variable
pointing to a specific address in a memory pointed by another variable.

Pointer Declaration Syntax


The declaration of C++ takes the following syntax:
datatype *variable_name;

 The datatype is the base type of the pointer which must be a valid C+
+ data type.
 The variable_name is should be the name of the pointer variable.
 Asterisk used above for pointer declaration is similar to asterisk used
to perform multiplication operation. It is the asterisk that marks the
variable as a pointer.

Here is an example of valid pointer declarations in C++:


int *x; // a pointer to integer
double *x; // a pointer to double
float *x; // a pointer to float
char *ch // a pointer to a character

Reference operator (&) and Deference operator


(*)
The reference operator (&) returns the variable’s address.

The dereference operator (*) helps us get the value that has been stored in
a memory address.

For example:

If we have a variable given the name num, stored in the address 0x234 and
storing the value 28.
The reference operator (&) will return 0x234.

The dereference operator (*) will return 5.

Example 1:
#include <iostream>
using namespace std;
int main() {
int x = 27;
int *ip;
ip = &x;
cout << "Value of x is : ";
cout << x << endl;
cout << "Value of ip is : ";
cout << ip<< endl;
cout << "Value of *ip is : ";
cout << *ip << endl;
return 0;
}
Output:

How this works:

C++ Pointer Arithmetic


As you understood pointer is an address which is a numeric value; therefore, you
can perform arithmetic operations on a pointer just as you can a numeric value.
There are four arithmetic operators that can be used on pointers: ++, --, +, and -
To understand pointer arithmetic, let us consider that ptr is an integer pointer which
points to the address 1000. Assuming 32-bit integers, let us perform the following
arithmetic operation on the pointer −
ptr++
the ptr will point to the location 1004 because each time ptr is incremented, it will
point to the next integer. This operation will move the pointer to next memory
location without impacting actual value at the memory location. If ptr points to a
character whose address is 1000, then above operation will point to the location
1001 because next character will be available at 1001.

Incrementing a Pointer
We prefer using a pointer in our program instead of an array because the variable
pointer can be incremented, unlike the array name which cannot be incremented
because it is a constant pointer. The following program increments the variable
pointer to access each succeeding element of the array −
Live Demo

#include <iostream>

using namespace std;


const int MAX = 3;

int main () {
int var[MAX] = {10, 100, 200};
int *ptr;

// let us have array address in pointer.


ptr = var;

for (int i = 0; i < MAX; i++) {


cout << "Address of var[" << i << "] = ";
cout << ptr << endl;

cout << "Value of var[" << i << "] = ";


cout << *ptr << endl;

// point to the next location


ptr++;
}

return 0;
}

When the above code is compiled and executed, it produces result something as
follows −
Address of var[0] = 0xbfa088b0
Value of var[0] = 10
Address of var[1] = 0xbfa088b4
Value of var[1] = 100
Address of var[2] = 0xbfa088b8
Value of var[2] = 200
Decrementing a Pointer
The same considerations apply to decrementing a pointer, which decreases its
value by the number of bytes of its data type as shown below −
Live Demo

#include <iostream>

using namespace std;


const int MAX = 3;

int main () {
int var[MAX] = {10, 100, 200};
int *ptr;

// let us have address of the last element in pointer.


ptr = &var[MAX-1];

for (int i = MAX; i > 0; i--) {


cout << "Address of var[" << i << "] = ";
cout << ptr << endl;

cout << "Value of var[" << i << "] = ";


cout << *ptr << endl;

// point to the previous location


ptr--;
}

return 0;
}

When the above code is compiled and executed, it produces result something as
follows −
Address of var[3] = 0xbfdb70f8
Value of var[3] = 200
Address of var[2] = 0xbfdb70f4
Value of var[2] = 100
Address of var[1] = 0xbfdb70f0
Value of var[1] = 10

Pointer Comparisons
Pointers may be compared by using relational operators, such as ==, <, and >. If p1
and p2 point to variables that are related to each other, such as elements of the
same array, then p1 and p2 can be meaningfully compared.
The following program modifies the previous example one by incrementing the
variable pointer so long as the address to which it points is either less than or equal
to the address of the last element of the array, which is &var[MAX - 1] −
Live Demo

#include <iostream>

using namespace std;


const int MAX = 3;

int main () {
int var[MAX] = {10, 100, 200};
int *ptr;

// let us have address of the first element in pointer.


ptr = var;
int i = 0;

while ( ptr <= &var[MAX - 1] ) {


cout << "Address of var[" << i << "] = ";
cout << ptr << endl;

cout << "Value of var[" << i << "] = ";


cout << *ptr << endl;

// point to the previous location


ptr++;
i++;
}

return 0;
}

When the above code is compiled and executed, it produces result something as
follows −
Address of var[0] = 0xbfce42d0
Value of var[0] = 10
Address of var[1] = 0xbfce42d4
Value of var[1] = 100
Address of var[2] = 0xbfce42d8
Value of var[2] = 200

Using Pointers with Objects


A pointer to a C++ class is done exactly the same way as a pointer to a structure and
to access members of a pointer to a class you use the member access operator ->
operator, just as you do with pointers to structures. Also as with all pointers, you
must initialize the pointer before using it.

For accessing normal data members we use the dot . operator with


object and -> qith pointer to object. But when we have a pointer to
data member, we have to dereference that pointer to get what its
pointing to, hence it becomes,

Object.*pointerToMember

Copy
and with pointer to object, it can be accessed by writing,

ObjectPointer->*pointerToMember

Lets take an example, to understand the complete concept.


class Data
{
public:
int a;
void print()
{
cout << "a is "<< a;
}
};

int main()
{
Data d, *dp;
dp = &d; // pointer to object

int Data::*ptr=&Data::a; // pointer to data member 'a'

d.*ptr=10;
d.print();

dp->*ptr=20;
dp->print();
}
Output:
a is 10
a is 20
C++ this Pointer
In C++ programming, this is a keyword that refers to the current instance of the
class. There can be 3 main usage of this keyword in C++.

o It can be used to pass current object as a parameter to another method.


o It can be used to refer current class instance variable.
o It can be used to declare indexers.

C++ this Pointer Example


Let's see the example of this keyword in C++ that refers to the fields of current class.

1. #include <iostream>  
2. class Employee {  
3.    public:  
4.        int id; //data member (also instance variable)      
5.        string name; //data member(also instance variable)  
6.        float salary;  
7.        Employee(int id, string name, float salary)    
8.         {    
9.              this->id = id;    
10.             this->name = name;    
11.             this->salary = salary;   
12.         }    
13.        void display()    
14.         {    
15.             cout<<id<<"  "<<name<<"  "<<salary<<endl;    
16.         }    
17. };  
18. int main() {  
19.     Employee e1 =Employee(101, "Sonoo", 890000); //creating an object of Em
ployee   
20.     Employee e2=Employee(102, "Nakul", 59000); //creating an object of Emplo
yee  
21.     e1.display();    
22.     e2.display();    
23.     return 0;  
24. }  

Output:

101 Sonoo 890000


102 Nakul 59000

Pointer to Derived Class

In C++, we can declare a pointer points to the base class as well as derive class. 
Consider below example to understand pointer to derived class

#include<iostream.h>
class base
{
        public:
        int n1;
        void show()
        {
              cout<<”\nn1 = “<<n1;
        }
};
class derive : public base
{
        public:
        int n2;
        void show()
        {
              cout<<”\nn1 = “<<n1;
              cout<<”\nn2 = “<<n2;              
        }
};
int main()
{
      base b;
      base *bptr;        //base pointer
    cout<<”Pointer of base class points to it”;
    bptr=&b;              //address of base class
      bptr->n1=44;                    //access base class via base pointer
      bptr->show();
     derive d;
    cout<<”\n”;
    bptr=&d;              //address of derive class
      bptr->n1=66;                    //access derive class via base pointer
      bptr->show();
      return 0;
}
Output
Pointer of base class points to it
n1 = 44
Pointer of base class points to derive class
n1=66
Here the show() method is the overridden method, bptr execute show() method of ‘base’ class
twice and display its content. Even though bptr first points to ‘base’ and second time points to
‘derive’ ,both the time bptr->show() executes the ‘base’ method show()

C++ Polymorphism
The term "Polymorphism" is the combination of "poly" + "morphs" which means many
forms. It is a greek word. In object-oriented programming, we use 3 main concepts:
inheritance, encapsulation, and polymorphism.

Real Life Example Of Polymorphism


Let's consider a real-life example of polymorphism. A lady behaves like a teacher in a
classroom, mother or daughter in a home and customer in a market. Here, a single person is
behaving differently according to the situations.

There are two types of polymorphism in C++:

o Compile time polymorphism: The overloaded functions are invoked by matching


the type and number of arguments. This information is available at the compile time
and, therefore, compiler selects the appropriate function at the compile time. It is
achieved by function overloading and operator overloading which is also known as
static binding or early binding. Now, let's consider the case where function name and
prototype is same.

1.    class A                                  //  base class declaration.  
2.   {  
3.        int a;  
4.        public:  
5.        void display()  
6.        {   
7.              cout<< "Class A ";  
8.         }  
9.   };  
10. class B : public A                       //  derived class declaration.  
11. {  
12.     int b;  
13.     public:  
14.    void display()  
15.   {  
16.         cout<<"Class B";  
17.   }  
18. };  

In the above case, the prototype of display() function is the same in both the base
and derived class. Therefore, the static binding cannot be applied. It would be great
if the appropriate function is selected at the run time. This is known as run time
polymorphism.

o Run time polymorphism: Run time polymorphism is achieved when the


object's method is invoked at the run time instead of compile time. It is
achieved by method overriding which is also known as dynamic binding or
late binding.

Differences b/w compile time and run time


polymorphism.

Compile time polymorphism Run time polymorphism

The function to be invoked is known at the The function to be invoked is known


compile time. at the run time.

It is also known as overloading, early It is also known as overriding,


binding and static binding. Dynamic binding and late binding.

Overloading is a compile time Overriding is a run time


polymorphism where more than one polymorphism where more than one
method is having the same name but with method is having the same name,
the different number of parameters or the number of parameters and the type
type of the parameters. of the parameters.

It is achieved by function overloading and It is achieved by virtual functions and


operator overloading. pointers.

It provides fast execution as it is known at It provides slow execution as it is


the compile time. known at the run time.

It is less flexible as mainly all the things It is more flexible as all the things
execute at the compile time. execute at the run time.

C++ Runtime Polymorphism Example


Let's see a simple example of run time polymorphism in C++.

// an example without the virtual keyword.

1. #include <iostream>    
2. using namespace std;    
3. class Animal {    
4.     public:    
5. void eat(){      
6. cout<<"Eating...";      
7.     }        
8. };     
9. class Dog: public Animal      
10. {      
11.  public:    
12.  void eat()      
13.     {           cout<<"Eating bread...";      
14.     }      
15. };    
16. int main(void) {    
17.    Dog d = Dog();      
18.    d.eat();    
19.    return 0;    
20. }    

1.  Compile Time Polymorphism 

In compile-time polymorphism, a function is called at the time of program compilation.


We call this type of polymorphism as early binding or Static binding.

 Function overloading and operator overloading is the type of Compile time


polymorphism.

I. Function Overloading

Function overloading means one function can perform many tasks. In C++, a single
function is used to perform many tasks with the same name and different types of
arguments. In the function overloading function will call at the time of program
compilation. It is an example of compile-time polymorphism.

In the below example, A function ADD() is used to perform two tasks. The two asks
would be to add two integer values and add two strings (concatenate). 

Readability of the program increases by function overloading. It is achieved by using the


same name for the same action.

Source Code:
1 #include <iostream>

2 using namespace std;

class Addition {
3
public:
4

5     int ADD(int X,int Y)   // Function with parameter


6     {
7         return X+Y;     // this function is performing addition of  two Integer val

8     }

9     int ADD() {              // Function with same name but without parameter

        string a= "HELLO";
10
        string b="SAM";   // in this function concatenation is performed
11
       string c= a+b;
12
       cout<<c<<endl;
13
        
14
    }
15
};
16 int main(void) {
17     Addition obj;   // Object is created 

18     cout<<obj.ADD(128, 15)<<endl; //first method is called

19     obj.ADD();  // second method is called

    return 0;
20
}
21

22

Output

143

HELLOSAM

In the above example, we use function ADD() to perform many tasks which is a property
of polymorphism in C++.
II. Operator Overloading

Operator overloading means defining additional tasks to operators without changing its
actual meaning. We do this by using operator function.

The purpose of operator overloading is to provide a special meaning to the user-defined


data types.

The advantage of Operators overloading is to perform different operations on the same


operand.

Source Code
1 #include <iostream> 

2 using namespace std; 

class A 
3

4
     
5
    string x; 
6
      public: 
7
      A(){} 
8     A(string i) 
9     { 
10        x=i; 

11     } 

12     void operator+(A); 

    void display(); 
13
}; 
14
   
15
void A:: operator+(A a) 
16

17
      
18
    string m = x+a.x; 
19
    cout<<"The result of the addition of two objects is : "<<m; 
20

21
   
22

23 int main() 
24 { 

25     A a1("Welcome"); 

26     A a2("back"); 

27     a1+a2; 

    return 0; 
28
}
29

30

Output

The result of the addition of two objects is: Welcomeback

2. Runtime Polymorphism

In a Runtime polymorphism, functions are called at the time the program execution.
Hence, it is known as late binding or dynamic binding.

Function overriding is a part of runtime polymorphism. In function overriding, more than


one method has the same name with different types of the parameter list. 

It is achieved by using virtual functions and pointers. It provides slow execution as it is


known at the run time. Thus, It is more flexible as all the things executed at the run time.

I. Function overriding

In function overriding, we give the new definition to base class function in the derived
class. At that time, we can say the base function has been overridden. It can be only
possible in the ‘derived class’. In function overriding, we have two definitions of the
same function, one in the superclass and one in the derived class. The decision about
which function definition requires calling happens at runtime. That is the reason we call
it ‘Runtime polymorphism’.

Source code
1

2 #include <iostream> 

3 using namespace std; 

4 class Animal { 

    public: 
5
void function(){   
6
cout<<"Eating..."<<endl;   
7
    }     
8
};  
9 class Man: public Animal   
10 {   
11  public: 

12  void function()   

13     {   

       cout<<"Walking ..."<<endl;   
14
    }   
15
}; 
16
int main(void) { 
17
 Animal A =Animal();
18
   A.function();   //parent class object
19    Man m = Man();   
20    m.function();   // child class object

21    

22    return 0; 

23 }

24
Output

Eating …..

Walking……

II. Virtual Function

A virtual function is declared by keyword virtual. The return type of virtual function may
be int, float, void.

A virtual function is a member function in the base class. We can redefine it in a derived
class. It is part of run time polymorphism. The declaration of the virtual function must be
in the base class by using the keyword virtual. A virtual function is not static.  

The virtual function helps to tell the compiler to perform dynamic binding or late binding
on the function.

If it is necessary to use a single pointer to refer to all the different classes’ objects. This is
because we will have to create a pointer to the base class that refers to all the derived
objects.

 But, when the base class pointer contains the derived class address, the object always
executes the base class function. For resolving this problem, we use the virtual function.

When we declare a virtual function, the compiler determines which function to invoke at
runtime.

Let’s see the below example for understanding how the program execution happens
without virtual function and with virtual function.

Source code
1 //without virtual Function
2

4  
#include <iostream> 
5
using namespace std; 
6
class Add
7

8
   int x=5, y=20; 
9
    public: 
10     void display()  //overridden function
11     { 

12         cout << "Value of x is : " << x+y<<endl; 

13     } 

14 }; 

class Substract: public Add


15

16
    int y = 10,z=30; 
17
    public: 
18
    void display()  //overridden function
19     { 
20         cout << "Value of y is : " <<y-z<<endl; 

21     } 

22 }; 

23 int main() 


24
    Add *m;           //base class pointer .it can only access the base class memb
25
    Substract s;     // making object of derived class
26
    m = &s; 
27
   m->display();      // Accessing the function by using base class  pointer
28     return 0; 
29 } 
30
Output

Value of x is: 25

Virtual Function used to invoke the derived class in a program.

Source Code
1 #include<iostream>

2 using namespace std;

3  
class Add
4
{
5
public:
6
    virtual void print ()
7
    { int a=20, b=30;
8      cout<< " base class Action is:"<<a+b <<endl;
9       }
10  
11     void show ()

12     { cout<< "show base class" <<endl; }

13 };

14  
class Sub: public Add
15
{
16
public:
17
    void print () //print () is already virtual function in derived class, we could
18
    { int x=20,y=10;
19
      
20
    cout<< " derived class Action:"<<x-y <<endl; }
21
 
22     void show ()
23     { cout<< "show derived class" <<endl; }
24

25
};
26
 
27
//main function
28
int main()
29 {
30     Add *aptr;
31     Sub s;

32     aptr = &s;

33      

34     //virtual function, binded at runtime (Runtime polymorphism)

    aptr->print();
35
     
36
    // Non-virtual function, binded at compile time
37
    aptr->show();
38
 
39
    return 0;
40
}
41

42

Output

 derived class Action:10

Pure virtual Function

When the function has no definition, we call such functions as “Do-nothing function or
Pure virtual function”. The declaration of this function happens in the base class with no
definition.
Source Code
1 #include <iostream> 
2 using namespace std; 
3 class Animal 
4 { 
5 public: 
6 virtual void show() = 0;  //Pure virtual function declaration.
7 }; 
8 class Man: public Animal 
9 { 
10 public: 
11 void show() 
12 { 
13 cout << "Man is the part of animal husbandry " << endl; 
14 } 
15 }; 
16 int main() 
17 { 
18 Animal *aptr; //Base class pointer
19 //Animal a; 
20 Man m;  //derived class object creation.
21 aptr = &m; 
22 aptr->show(); 
23 return 0; 
24 }
Unary Operator Overloading:
Q. Write a C++ program to overload unary operators that is increment and decrement.

Answer:

Operator overloading is a type of polymorphism in which an operator is overloaded to give user


defined meaning to it. It is used to perform operation on user-defined data type.
Following program is overloading unary operators: increment (++) and decrement (--).
#include<iostream>
using namespace std;
class IncreDecre
{
        int a, b;
     public:
        void accept()
        {
                cout<<"\n Enter Two Numbers : \n";
                cout<<" ";
                cin>>a;
                cout<<" ";
                cin>>b;
        }
        void operator--() //Overload Unary Decrement
        {
                a--;
                b--;
        }
        void operator++() //Overload Unary Increment
        {
                a++;
                b++;
        }
        void display()
        {
                cout<<"\n A : "<<a;
                cout<<"\n B : "<<b;
        }
};
int main()
{
        IncreDecre id;
        id.accept();
        --id;
        cout<<"\n After Decrementing : ";
        id.display();
        ++id;
        ++id;
        cout<<"\n\n After Incrementing : ";
        id.display();
        return 0;
}

Output:

Binary Operator Overloading

As the name suggests, those operators which operate on two operands or data are called binary
operators.
Here is an example to show how binary operators are overloaded in C++.
Example: C++ program to illustrate binary operator overloading
#include<iostream>
using namespace std;

class complex
{
private:
int real,imag;
public:
void getvalue()
{
cout<<"Enter the value of real number:";
cin>>real;
cout<<"Enter the value of imaginary number:";
cin>>imag;
}
complex operator+(complex obj)
{
complex temp;
temp.real=real+obj.real;
temp.imag=imag+obj.imag;
return(temp);
}
complex operator-(complex obj)
{
complex temp;
temp.real=real-obj.real;
temp.imag=imag-obj.imag;
return(temp);
}
void display()
{
cout<<real<<"+"<<"("<<imag<<")"<<"i"<<"\n";
}
};

int main()
{
complex c1,c2,c3,c4;

c1.getvalue();
c2.getvalue();

c3 = c1+c2;
c4 = c1-c2;

cout<<"Result is:\n";
c3.display();
c4.display();

return 0;
}

You might also like