Friday, 31 May 2013

Operator Overloading in C++


Introduction Operator Overloading
  • Operator overloading provides a flexible option for the creation of new definition for most of the C++ operators.
  • When an operator is overloaded its original meaning is not lost.

Consider the following example:
#include<iostream.h>
class complex
{
     private:
     int a,b;
     public:
     void getdata();
     void showdata();  
};
void complex:: getdata()
{
     cout<<”Enter two numbers”;
     cin>>a>>b;
}
void complex:: showdata()
{
     cout<<”a=”<<a<<”b=”<<b;
}
void main()
{
  complex c1,c2,c3;
  c1.getdata();
  c2.getdata();
  c3=c1+c2;  //Error
  c3.show();
}

l  Notice line c3=c1+c2;
l  This line generates compile time error.
l  Error occurs as operands to the operator ‘+’ are not of primitive type; rather they are of complex type. Every primitive data type is enriched with several operators. Defining working of operators is responsibility of programmer who defines data type. Hence, we have to define behavior of operator ‘+’ for complex.
l  Defining new meaning of ‘+’ does not make any loss to previous meaning of operator ‘+’ with respect to primitive data type.
l  Operators can be defined in the class just like any other member function.
l  To make operator as a valid function name we use keyword operator.
l  The following example illustrates definition of ‘+’:

#include<iostream.h>
class complex
{
     private:
            int a,b;
     public:
            void getdata();
            void showdata();        
            complex operator +(complex);
};
complex complex :: operator +(complex c)
{
  complex temp;
  temp.a=a+c.a;
  temp.b=b+c.b;
  return(temp);
}
void complex:: getdata()
{
            cout<<”Enter two numbers”;
            cin>>a>>b;
}
void complex:: showdata()
{
            cout<<”a=”<<a<<”b=”<<b;
}
void main()
{
  complex c1,c2,c3;
  c1.getdata();
  c2.getdata();
  c3=c1+c2; 
  c3.show();
}

l  In this example observe the line c3=c1+c2;
l  Here, c1 calls member ‘+’ and pass c2 as a parameter. The value of c2 will be copied to object c.
l  Read carefully the code of member ‘+’ in class complex.
l  Object c contains the same data as object c2 contains in main().
l  As c1 is used to call operator ‘+’, variables a and b mentioned in the body of ‘+’ are of object c1.
l  Addition of data of objects are then stored in a temporary object temp;
l  The value stored in temp is then returned to main(), which is received in object c3.
l  Original meaning of operator ‘+’ with respect to primitive data types is preserved.
l  Now we have multiple meanings of operator ‘+’. Compiler will resolve the version of ‘+’ by type of operands.
l  Same operator has now multiple jobs, this is known as operator overloading.

List of operators that can not be overloaded
There are few operators that can not be overloaded. They are:

l  Conditional operator-   ?:
l  Dereference operator-  *.
l  Dot operator-                .
l  Size of operator-          sizeof()
l  Preprocessor directive-  # and ##
                 
There are few more examples that illustrate overloading of various operators:
Overload unary minus (-)
#include<iostream.h>
class complex
{
     private:
            int a,b;
     public:
            void getdata();
            void showdata();        
            complex operator -();
};
complex complex ::operator –()
{
  complex temp;
  temp.a = -a;
  temp.b = -b;
  return(temp);
}
void main()
{
  complex c1, c2;
  c1.getdata();
  c1.show();
  c2= -c1;
  c1.show();
  c2.show();
}

l  Notice that the unary operator doesn’t need any argument.
l  Unary minus is called by c1and hence a and b in definition of unary minus are of c1.
l  Values of a and b of c1 are copied in variables a and b of temp with invert sign (see code in unary minus)
l  The value of temp is returned and received by c2.

Overload relational operator equal to (==)
#include<iostream.h>
class complex
{
     private:
            int a,b;
     public:
            void getdata();
            void showdata();        
            int operator ==(complex);
};
int complex ::operator ==(complex c)
{
  if(a==c.a && b==c.b)
     return(1);
 else
     return(0);
}
void main()
{
  complex c1, c2;
  c1.getdata();
  c2.getdata();
  if(c2==c1)
cout<<”objects are equal”;
 else
            cout<<”objects are not equal”;
}

l  Here, return type of operator is int.
l  If corresponding member variables of both the objects are equal operator returns 1 otherwise 0.
Overload increment operator ++
#include<iostream.h>
class complex
{
     private:
            int a,b;
     public:
            void getdata();
            void showdata();        
            complex operator ++();   //Pre increment
            complex operator ++(int); //Post increment
};
complex complex ::operator ++()
{
   complex temp;
   temp.a= ++a;
   temp.b= ++b;
   return(temp);
}
complex complex ::operator ++(int)
{
   complex temp;
   temp.a= a++;
   temp.b= b++;
   return(temp);
}
void main()
{
  complex c1, c2;
  c1.getdata();
  c2.getdata();
  c3=c1++;  //call to post increment
  c3.show();
  c3=++c2;  //call to pre increment
  c3.show();
}


l  Here, we overload two versions of increment operator. One with no argument is pre-increment and other one with one argument is post increment.
l  Remember, in post increment argument int is mentioned to distinguish between two versions of increment operator. We do not actually pass any integer value during call of post increment.
l  In pre-increment version we increment values of a and b then copy them in variables of temp. Function returns temp which contains incremented values.
l  In post-increment version we copy the values of a and b in variables of temp then increment values of a and b. Function returns temp which contains old values (values before increment). 

Constructors and destructors in C++


Constructor
l  A constructor is a member function of a class.
l  It is a special member function of a class whose name is same as the name of class.
l  It has no return type.
l  Constructors do not call explicitly.
l  It is invoked implicitly when an object of class is created.
l  An implicit constructor is generated by compiler whenever we do not write any constructor in class definition. This implicit constructor would be called during object creation.
l  If we define a constructor in the class then there will be no implicit constructor created by class.
l  Constructor should always be defined in public as we create objects outside the class definition. Although there are scenarios where we would like to define constructor in private.
l  Constructor solves the problem of initialization. We can initialize variables of primitive data type during creation of variable but this feature is optional.

For example: int x=3; //creation of variable x and initialize it with a value 3
Let us assume complex is a user defined data type.
complex c1=4; //error this is called problem of initialization during creation of object


l  This problem can be solved with constructor. Following example illustrates this in detail:
#include<iostream.h>
class complex
{
     private:
     int a,b;
     public:
     complex(int x) { a=x; b=x; }
     void getdata();
     void showdata();  
};
void complex:: getdata()
{
     cout<<”Enter two numbers”;
     cin>>a>>b;
}
void complex:: showdata()
{
     cout<<”a=”<<a<<”b=”<<b;
}
void main()
{
  complex c1=3;  //constructor is called
  c1.show();
}

l  Here, constructor is called when object c1 is created in main() function
l  Notice that a value 3 is assigned to c1. This notation is resolved as; during creation of object c1 constructor is called and 3 is passed as an argument, which is then received by variable x in constructor. Value of x is copied into a and b. Hence, member variables of object c1 are initialized during object creation.
l  Please note the following declarations
complex c1(3);
complex c1=complex(3);

l  These two notations and the one which is used in function main()(complex c1=3;} are all same. You can choose the one that you like the most.
l  What happens if we remain class specification same and change the code of function main().
New definition of main(). For class definition please refer above example:
void main()
{
  complex c1=3;
  complex c2;  //error: no proper match for the constructor in class complex
 …
}


l  Why this error occurs? Answer is simple there is only one constructor in class complex which takes one argument of type int. So the first line is valid. In the second line we are creating an object with no arguments for constructor. Also note that there is no implicit constructor created by compiler as compiler do such only when we do not define any constructor in the class.
l  To remove this error we should define another constructor in the class which takes no argument.
l  Now consider another example which is remarkable modification in the previous example
#include<iostream.h>
class complex
{
     private:
     int a,b;
     public:
     complex() { } //default constructor, constructor with no argument
            complex(int x)
{ a=x; b=x; } //parameterized constructor, one argument
     complex (int x, int y)
{ a=x; b=y; } //parameterize constructor for two arguments
            void getdata();
     void showdata();  
};
void complex:: getdata()
{
     cout<<”Enter two numbers”;
     cin>>a>>b;
}
void complex:: showdata()
{
     cout<<”a=”<<a<<”b=”<<b;
}
void main()
{
  complex c1=3;  //constructor with one argument is called
     complex c2(3,4); //constructor with two arguments is called
     complex c3; //default constructor is called
     c1.show();
  c2.show();
  c3.show();
}

l  Here, three versions of constructors are defined in the class complex.
l  Compiler will resolve the version of constructor by examine argument list. This mechanism is called constructor overloading. Since this happens during compilation it is known as compile time polymorphism.

Copy Constructor

l  Whenever an object is created and initialize by the object of same class, no need to define another constructor as bitwise copy of existing object is assigned to newly created object. But whenever you desire to change this traditional mechanism of bitwise copying, you can create a copy constructor.
l  Following example illustrates copy constructor:

#include<iostream.h>
class complex
{
     private:
     int a,b;
     public:
     complex() { } //default constructor, constructor with no argument
            complex(int x)
{ a=x; b=x; } //parameterized constructor for one argument
            complex (int x, int y)
{ a=x; b=y; } //parameterize constructor for two arguments
            complex (complex &c) //copy constructor
{   
   a= c.b;   
   b= c.a;
}
void getdata();
     void showdata();  
};
void complex:: getdata()
{
     cout<<”Enter two numbers”;
     cin>>a>>b;
}
void complex:: showdata()
{
     cout<<”a=”<<a<<”b=”<<b;
}
void main()
{
  complex c1=3;  //constructor with one argument is called
     complex c2(3,4); //constructor with two arguments is called
     complex c3; //default constructor is called
     complex c4=c2;  //copy constructor is called
     c1.show();
  c2.show();
  c3.show();
  c4.show();
}

l  Here, copy constructor is called during creation of object c4. We are passing reference of c2. Thus c is reference object in copy constructor.
l  Remember always to pass reference in copy constructor and not pass value of object otherwise it yields an error message. It is due to avoid recursive call of copy constructor.

Destructor

l  Destructor is also a member function of class.
l  The name of destructor is same as the name of class but preceded with a tilde (~) sign.
l  It has no return type.
l  It never takes any argument and hence can not be overloaded.
l  Destructor invokes automatically for an object, when object goes out of scope.
l  Destructor is called when object is destroyed. Whatever we code in destructor will run during object destruction.
l  Sometimes it is needed to perform some actions when an object is destroyed. For example, an object that allocates memory when it is created will want to free that memory when it is destroyed.
l  The following example illustrates the use of destructor.
#include<iostream.h>
class complex
{
     private:
            int a,b;
     public:
            complex() { } //default constructor, constructor with no argument
            complex(int x) { a=x; b=x; } //parameterized constructor for one argument
            complex (int x, int y) { a=x; b=y; } //parameterize constructor for two arguments
            complex (complex &c) //copy constructor
{          
   a= c.b;   
   b= c.a;
}
~complex()
{ cout<<”You are in destructor”; }
void getdata();
            void showdata();        
};
void complex:: getdata()
{
            cout<<”Enter two numbers”;
            cin>>a>>b;
}
void complex:: showdata()
{
            cout<<”a=”<<a<<”b=”<<b;
}
void main()
{
  complex c1=3;  //constructor with one argument is called
  complex c2(3,4); //constructor with two arguments is called
  complex c3; //default constructor is called
  complex c4=c2;  //copy constructor is called
  c1.show();
  c2.show();
  c3.show();
  c4.show();
}

l  We have added one more function in the previous program that is destructor.
l  You can see name of destructor is same as the name of the class preceded by a symbol called tilde (~).
l  This function is called every time when object goes out of scope.

Static Member variable and static member function
Members of a class can be qualified as static by using keyword static. Members those are static are different in behavior from other non static members of the class.
Life of the static members extends the entire run of the program.

Static member variable

l  When you declare a data member in a class declaration, the static keyword specifies that one copy of the member is shared by all instances of the class.
l  Static member variables need to be defined outside the class.
l  Static member variables are not associated with any object and thus also known as class variable.
l  Although object can access public static member variables of the class using dot (.) operator but that doesn’t mean that static member variable is associated with that object.
l  Static member variable can also be accessed with class name and scope resolution operator.
l  Memory allocation of static member variable doesn’t depend on creation of object of class.
l  Static member variables can be accessed through any of class member function, no matter if they are static or not.
l  Life time of static members extends the entire program.

Example of static member variables

#include<iostream.h>

class  marksheet
{
  private:
          int sub1,sub2,sub3,sub4,sub5;
          float per;
          int result; 
  public:
          static int displaycount;
            void getmarks()
            {
                        cout<<”Enter marks of five subjects:”;
                        cin>>sub1>>sub2>>sub3>>sub4>>sub5;
                        result=result_generation();
                        per=percentage();
            }
            int result_generation()
            {
                        if(sub1>=35&&sub2>=35&&sub3>=35&&sub4>=35&&sub5>=35)
                                    return(1);
                        return(0);
            }
            float percentage()
{
            int sum=sub1+sub2+sub3+sub4+sub5;
                        return(sum/5.0);
            }
            void show_result()
{
            cout<<”Subject 1: “<<sub1<<endl;
            cout<<”Subject 2: “<<sub2<<endl;
            cout<<”Subject 3: “<<sub3<<endl;
            cout<<”Subject 4: “<<sub4<<endl;
            cout<<”Subject 5: “<<sub5<<endl;
            cout<<”Result: ”;
            result==1? cout<<”PASS” : cout<<”FAIL”;
            cout<<”\nPercentage: “;
            result==1?cout<<per:;
            displaycount++;
            cout<<”Display No: “<<displaycount;
      }
};
int marksheet:: displaycount;
void main()
{
            marksheet m1,m2,m3;
            m1.getmarks();
            m1.showresult();
            m2.getmarks();
            m2.showresult();
            m3.getmarks();
            m3.showresult();
}

Try above program and see result
You will observe every time showresult() increments displaycount. No matter who calls showresult, there is only one copy of displaycount used by showresult().

In the above program, displaycount is a static member variable. Please go the points written above this program.


Static member function

l  Static member functions can access only static members of the same class.
l  Static member function can be called by class name and scope resolution operator.
l  Static member functions can also be accessed through object name and dot (.) operator, but that doesn’t mean that the static member function could access non static member variables of object.
l  You might have a surprised, why we use static member function while we can access static member variables from non static member function. Answer is simple, we can not call non static member functions from out side the class without using object and dot (.) operator. But we know that existence of static member variable does not depend on creation of object. So how we can access static member variables (private) from outside the class when none of the object is created? It can be accessed through static member functions.
l  Since static member functions are not associated with any particular object they can never access object’s non static variables. Although we can create an object of same class in static member function and can access object’s member from there.
l   

Example
#include<iostream.h>

class  marksheet
{
  private:
          int sub1,sub2,sub3,sub4,sub5;
          float per;
          int result; 
          static int displaycount;
  public:
            void getmarks()
            {
                        cout<<”Enter marks of five subjects:”;
                        cin>>sub1>>sub2>>sub3>>sub4>>sub5;
                        result=result_generation();
                        per=percentage();
            }
            int result_generation()
            {
                        if(sub1>=35&&sub2>=35&&sub3>=35&&sub4>=35&&sub5>=35)
                                    return(1);
                        return(0);
            }
            float percentage()
{
            int sum=sub1+sub2+sub3+sub4+sub5;
                        return(sum/5.0);
            }
            static int counter()
            {
                        displaycount++;
                        return(displaycount);
            }
            void show_result()
{
            cout<<”Subject 1: “<<sub1<<endl;
            cout<<”Subject 2: “<<sub2<<endl;
            cout<<”Subject 3: “<<sub3<<endl;
            cout<<”Subject 4: “<<sub4<<endl;
            cout<<”Subject 5: “<<sub5<<endl;
            cout<<”Result: ”;
            result==1? cout<<”PASS” : cout<<”FAIL”;
            cout<<”\nPercentage: “;
            result==1?cout<<per:;
      }
};
int marksheet:: displaycount;
void main()
{
            marksheet::counter();
            marksheet m1,m2,m3;
            m1.getmarks();
            m1.showresult();
            m1.counter();
            m2.getmarks();
            m2.showresult();
            m2.counter();
            m3.getmarks();
            m3.showresult();
            m3.counter();
}

Wednesday, 29 May 2013

Classes and Objects


Class
l  A class is usually represents a noun.
l  It encapsulates the state and behavior of the concept it represents.
l  It encapsulates the state through data placeholders called attributes(or member variables)
l  It encapsulates behavior through sections of code called methods (functions).
Object
l  Object is an instance of class.
l  Object is a runtime entity
l  Object is a physical representation of a class

An example of class

#include<iostream.h>
class distance
{
     private:
     int km,m,cm;
     public:
     void getdata()
     {
          cout<<”Enter KM, M, CM:”;
          cin>>km>>m>>cm;
     }
     void showdata()
     {
          cout<<”KM=”<<km<<”M=”<<m<<” CM=”<<cm;
     }
};
void main()
{
  distance d1,d2;
  d1.getdata();
  d2.getdata();
  d1.show();
  d2.show();
}

Access Specifiers

l  There are three access specifiers: private, protected and public.
l  These access specifiers are used to categorize access rules for class members
l  Those data members and member functions declared as private, can not accessed outside the class.
l  Those data members and member functions declared as public can accessed outside the class along with inside access
l  Protected works similar to private that is can not access from outside the class but the difference between private and protected will get clear in inheritance.

Properties of member functions
l  Member variables and member functions can be accessed from outside class with the help of object of the same class and dot operator, only when members are public.
l  Member functions can access other members of the same class regardless of their access category.
l  Member functions can access other members without using object and dot operator. For example, in above program getdata() is accessing km,m and cm without using object and dot operator. These variables are members of object who invoked member function getdata().
l  Member function can be defined inside or outside the class. If they are defined inside the class, mechanism is very clear from the above example, as we defined two member functions getdata() and showdata() inside the class.
l  When we intend to define member functions outside the class, we have to declare it inside the class. When we define member function outside, membership label should be placed between return type and function name. So the syntax is

return type Class name :: Function name (argument list)
{
… …...
}
l  All functions defined inside the class are inline by default. If definition of member function is written outside the class then inline keyword must use to make function inline.
l  Several different classes can use the same function name. The membership label will resolve their scope.

Function call by passing objects and returning objects

#include<iostream.h>
class complex
{
     private:
     int a;
     int b;
     public:
     void getdata();
     void showdata();
     complex add(complex);  
};
void complex:: getdata()
{
     cout<<”Enter two numbers”;
     cin>>a>>b;
}
void complex:: showdata()
{
     cout<<”a=”<<a<<”b=”<<b;
}
complex complex :: add(complex c)
{
  complex temp;
  temp.a=a+c.a;
  temp.b=b+c.b;
  return(temp);
}
void main()
{
  complex c1,c2,c3;
  c1.getdata();
  c2.getdata();
  c3=c1.add(c2);
  c3.show();
}

l  We have created three objects of type complex
l  We call getdata() twice first via c1 and then via c2.
l  Now member function add() is called via c1 and passes object c2 as a parameter.
l  In function add() value of c2 is received in object c.
l  We have created another object temp in function add() to temporary hold sum of c1 and c2.
l  Function add() returns object temp, this value is then get collected in object c3.
l  Show() function is next used to display content of c3.