Constructors and Destructors Unit 4 Constructors and Destructors
Introductions to Constructors When a variable is declared and if it is not initialized, it contains the garbage value. The programmer needs to initialize variables with appropriate values. This can be done through the public member functions. In the first step the object is created and in the second step the data members are initialized through public member functions. It could be better if the initialization is done at the time the object is created or declared. This can avoid calling the public member function to initialize the data members. This initialization is possible with constructors.
The constructor is a special member function of a class that is executed whenever an object is created. A constructor will have same name as the class and it does not have any return type at all, not even void. Constructors can be very useful for initializing the data members.
Syntax: class A { public: A() //constructor name is same as class name //body of the constructor } };
Characteristics of constructors Constructors have same name as the class name. Constructors are executed whenever an object is created or declared. Constructors have neither return type, nor void. The main function of the constructor is to initialize the data members. Constructors can have default values and can be overloaded. The constructor without arguments is called "Default Constructor". The constructor with arguments is called "Parameterized Constructor"
Destructors The destructors are also special member functions. They will also have the same name as class name, but proceeded by ~ (tilde) operator. The destructors are opposite to the constructors. The constructors are used to initialize the data members and destructors are used to destroy the objects whenever they are no longer needed.
Syntax: class A { public: A() //constructor name is same as class name //body of the constructor } ~A() //destructor name same as the class name //body of the destructor };//end of the class
Characteristics of Destructors Destructors have the same name as that of the class name, but proceeded by ~ (tilde) operator. Similar to constructor, the destructors do not have return type, or void. Destructors neither have default arguments, nor overloaded. Constructor and destructor make implicit calls to the new and delete operators respectively. Only one destructor can be defined for the class.
Applications with Constructors The initialization of the data members is carried out using the constructors. The constructor also allocates the memory to the object. When an object is declared or created it's data members are automatically initialized to the given values. The compiler automatically calls the constructors. The constructor is called with each object separately.
Write a C++ program to define a constructor and initialize the class data members with some constants. Write a C++ program to show that each object calls the constructor separately.
Constructors with Arguments (Parameterized Constructors) A default constructor does not have any parameter. It is also possible to create constructor with arguments, such constructors are called "parameterized constructors". This helps you to assign initial value to an object at the time of its creation.
There are two ways to call the constructors: 1. Implicit calling Syntax: class_name object_name(actual arguments); 2. Explicit calling class_name object_name=constructor(actual arguments);
Overloading Constructors Similar to the function, it is also possible to overload the constructors. A class can contain more than one constructors, as long as the argument list is different. This is known as "constructor overloading". All constructors are defined with same name as the class name. Depending upon on the number of arguments the compiler executes appropriate constructor.
Write a C++ program with multiple constructors for the single class? #include<iostream.h> #include<conio.h> class cse { int b,g; public: cse() //constructor b=25; g=35; } cse(int x,int y) //constructor b=x; g=y; cse(int x) //constructor b=g=x; void display() cout<<"The Boys are:"<<b<<endl; cout<<"The Girls are:"<<g<<endl; }; int main() cse ca,cb(15,45),cc(30); //calling different constructors clrscr(); cout<<"------ First Object:-----"<<endl; ca.display(); cout<<"-------Second Oject:------"<<endl; cb.display(); cout<<"-------Third Object:------"<<endl; cc.display(); getch(); return 0;
Array of Objects Using Constructors An array is a collection of elements of similar data types. We can also create an array of objects. The array elements are stored in contiguous memory locations. An array of objects is an important data structure when data is itself an object.
Constructors with Default arguments Similar to functions, it is also possible to declare constructors with default arguments. When the constructor is called with less or without arguments then the default arguments are used to initialize the data members.
Write a C++ program to demonstrate constructor with default argument? #include<iostream.h> #include<conio.h> #include<math.h> class power { int num,pr,ans; public: power(int n=5,int p=3) //default arguments num=n; pr=p; ans=pow(num,pr); } void display() cout<<num<<" power "<<pr<<" is "<<ans<<endl; }; int main() power p1,p2(2),p3(3,3); //calling constructor clrscr(); p1.display(); p2.display(); p3.display(); getch(); return 0;
Copy Constructors Copy Constructors are used to initialize object of a class with object of the same class. The constructor can take any argument including the user defined data type. It is possible to pass the reference (&) of the object as argument. Such declarations are called " Copy Constructor". There are two ways to copy the object with another object. 1) Implicit copy 2) Explicit copy.
Implicit copy: The constructor takes the object as argument. Syntax: class_name object( object); Explicit copy: The constructor is copied with another object. Syntax: class object1=object2;
The Const Objects Previously we discussed about const member function which are not allowed to change the data members. In same way we can also make the object constant by the keyword "const". In this case only the constructor can initialize the data members of the object. Characteristics: The data members of the const object will be read-only, any effort to alter the data members will cause to generate an error. The data members of the const object are also called "read-only" data members. The const object can access const member functions only.
Calling Constructors and Destructors The compiler will automatically calls the constructors and destructors. We can also call the constructors and destructors as the normal user-defined function. We use the scope resolution operator to call the constructor manually. Syntax: object_name.member_name::constructor(); object_name.member_name::~destructor();
Qualifier and Nested Classes The class declaration can also be done inside another class. While declaring the objects of such classes it is necessary to precede outer class. The inner class is called "nested class". The outer class is called "qualifier class". The use of nested classes will enhance the power of data abstraction and helps to construct more powerful data structures.
Anonymous Objects Generally objects are created with names. It is possible to create objects without names. Such objects are called "anonymous objects". The anonymous objects are exist, but are hidden. Using the "this" operator we get the address of the anonymous object.
Private Constructors & Destructors As the member functions are declared under the private section, it is also possible to declare the constructors and destructor as private. These private constructors and destructors are accessed using the public member functions of the same class. When the constructors and destructors are private, they cannot be executed implicitly, they can be called explicitly using the "this" operator. Every member holds the "this" pointer that points to the calling object.
#include<iostream.h> #include<conio.h> class A { private: int x; A() x=10; } ~A() cout<<" Object is destroyed:"<<endl; } public: void display() this->A::A(); //calling constructor cout<<"The value of x is:"<<x<<endl; this->A::~A(); //calling destructor }; int main() clrscr(); A *a; a->display(); getch(); return 0;
Dynamic Initialization using Constructors Initializing the data members at the time of program execution using the pointer is called "dynamic initialization". The benefit of this approach is that it allows different modes of the initialization using the constructor overloading. The pointer variables are used as arguments for the constructors.
#include<iostream.h> #include<conio.h> class cse { private: int b,g; public: cse(int *x) b=g=*x; } cse(int *x, int *y) b=*x; g=*y; } void display() cout<<"The Boys are:"<<b<<endl; cout<<"The girls are:"<<g<endl; } };
int main() { int x,y; clrscr(); cout<<"enter the data:"; cin>>x>>y; cse a(&x); cse b(&x,&y); a.display(); cout<<"\n==================="; b.display(); getch(); return 0; }
Dynamic Operators and Constructors When constructors and destructors are executed, they will use internally new and delete operators. Dynamic construction means allocation of memory by the constructor for the objects. Dynamic destruction means releasing the memory using the destructor.
Write a C++ program to demonstrate the Dynamic Operator and constructors and #include<iostream.h> #include<conio.h> class num { int *x; int s; public: num() s=number(); x=new int[s]; //dynamic allocation } ~num() cout<<"\nX is deleted:"; delete x; void input() cout<<"Enter the data:"; for(int i=0;i<s;i++) cin>>x[i]; int number() int n; cout<<"Enter number of elements:"; cin>>n; return n; void sum() int tot=0; tot=tot+x[i]; cout<<"The sum of all elements:"<<tot; };
int main() { clrscr(); num n1; n1.input(); n1.sum(); getch(); return 0; }
Recursive Constructor Similar to the normal and member functions, the constructors also support recursion. The process of calling the constructor by itself repeatedly until some condition is satisfied is called "recursive constructor". The following example explains this.
Show output Note: A triangular number or triangle number counts the objects that can form an equilateral triangle, as in the diagram on the right.
Constructor and Destructor with Static Members We can also declare static data members inside the class. When we declare static data members only one copy is created, all the objects will share the same copy. Static data members are used to know the number of objects created with that class.
Local Vs. Global Object The object declared outside all the function bodies is known as "global object". All the functions can access the global object. The object declared inside the function is called "local object". The scope of the local object is limited to its current block.
When local and global objects are declared with the same name then the scope resolution operator is used(::) to access the global object in the current scope.
#include<iostream.h> #include<conio.h> class text { public: void disp(char *c) cout<<c<<endl; } };
text t; //global object void main() { clrscr(); text t; //Local Object ::t.disp("global object accessing"); t.disp("local object accessing"); getch(); }
Part-II of 4th unit Operator Overloading and Type Conversion The capability to relate the existing operator with a member function and use the resulting operator with object of its class as its operand is called Operator Overloading.
Operator overloading is one of the important and useful feature of C++. The concept of operator overloading is somewhat similar to function overloading in which multiple functions use same name. A symbol that is used to perform an operation is called an Operator. It is used to perform an operation along with constants and variables. We cannot build an expression without operator. Operator overloading is one of most valuable concept introduced by C++ language. It is a type of polymorphism. C++ has number of data types such as int, float, double, char etc and number of operators such as +,-,*,/,% etc. Operator overloading helps to use these operator along with object of class. The objects can be used as normal variable in the expressions. Example: a=c+d; where a, c and d are objects.
The "operator" keyword The keyword operator defines new action or operation to the operator. The compiler cannot perform addition of two objects. Then the compiler may throw an error if addition of two objects is carried out. The compiler must be made aware of addition process of two objects. When an expression with object is encountered, the compiler searches for the definition of operator, in which code is written to perform an operation with two objects. This definition is written as follow:
return_type operator operator_symbol( parameters) Syntax: return_type operator operator_symbol( parameters) { statement1; statement2; } Example: number operator +(number D) number T; T.x=x+D.x; T.y=y+D.y; return T;
16.cpp Show output
Overloading unary operators Providing an explicit argument to the operator function is called unary operator overloading. The operators ++, --, and are unary operators. The unary ++ and- – are used as prefix and suffix with function. Example 16b.cpp show output
Operator return type The way how a function can return a value the operator overloading also can return a value and the same value can be assigned to other object also. The type of the function should be the type of the class. Show output retobj.cpp
#include<iostream.h> #include<conio.h> class plusplus { int n; public: plusplus() n=0; } plusplus operator++() plusplus p; p.n=n+1; return p; int getnum() return n; };
p1=++p2; //assigning p2 to p1 int main() { plusplus p1,p2; p1=++p2; //assigning p2 to p1 cout<<"The value of p2 is:"<<p2.getnum()<<endl; cout<<"The value of p1 is:"<<p1.getnum(); getch(); return 0; }
Constraint on Increment and Decrement Operators There exist no difference between prefix and postfix overloaded operator functions. The result will be same even if we use postfix or prefix operator in the operator overloading. To make some distinction between postfix and prefix notation a new syntax is used as follow:
syntax: operator ++(int) // post fix notation operator ++() // prefix notation
Overloading Binary Operators Binary operator requires two arguments or operands. These can be overloaded using member function or friend function. Overloading using member function Syntax: return_type operator + (obj1,obj2) { obj3=obj1+obj2; } Overloading using the friend function Friend functions can be used alternatively with member functions for overloading of binary operators. The friend function requires two operands as arguments. Friend functions are useful when we perform operations with different arguments.
Overloading with Friend Function Friend functions are more useful in operator overloading. They offer better flexibility than member functions. The difference between member function and friend function is that the member function takes the operands explicitly. On the other hand, the operands are passed to the friend function explicitly. The keyword "friend" precedes the function prototype.
Syntax: friend return_type operator operator_sybmol (var1, var2) { statement1; statement2; } Example program mul.cpp
Write a C++ program to multiply an integer and object using the friend function?
Overloading Assignment(=) Operator You can overload the assignment operator (=) just as you can other operators and it can be used to create an object just like the copy constructor. The assignment operator can be overloaded in two ways: Implicit overloading implic.cpp example program Syntax: n2=n1; Explicit overloading Explic.cpp Syntax n2.operator=(n1);
Type Conversion We know that, when constants and variables of different types are clubbed in a single expression, automatic type conversion takes place. This is done only for basic data types. The compiler is unknown about conversion from user defined data type to other data type. The programmer should write the routine that convert basic data type to user-defined data or vice versa. There are three possibilities of data conversion as given bellow: Conversion from Basic to Class type ( B-To-C) Conversion from Class to Basic Type (C –To-B) Conversion from Class to another Class Type( C-To-C)
Conversion from Class to Basic Type (C –To-B) During this conversion, the statement should satisfy the following conditions. The conversion function should not have any arguments. Do not mention return type. It should be a class member function.
Conversion from Class to another Class Type( C-To-C) When an object of one class is assigned to object of another class, it is necessary to give clear-cut instructions to the compiler how to make the conversion between two user-defined data types. There are two ways to convert object of one type to another. One way is, to define a conversion operator function in source class or a one-argument constructor in the destination. For example: X=A, Here X is an object of type XYZ and A is an object of ABC. The class ABC Data type is converted to class XYZ. The ABC class is called "Source" and The XYZ is called "Destination". We know the operator function operator data_type(). Here data type can be basic or user-defined data type.
Rules for Overloading Operators We cannot change the basic idea of an operator number of operands an operator expects precedence and associatively of operators or use default arguments with operators We should not change the natural meaning The meaning of the operato (+ does not mean subtraction!) The nature of the operator (3+4 == 4+3 The data types and residual value expected Whether it is an rvalued or lvalued resul Provide consistent definitions (if + is overloaded, then += should also be)
The overloaded operator should contain one operand of user-defined data type The overloaded operators have the same syntax as the original operator. There is no higher limit for the number to the number of overloading for any operator. Operator overloading is applicable within the scope in which overloading occurs. Only existing operator can be overloaded.
Some operators cannot be overloaded as bellow: :: scope resolution operator . direct member access operator .* direct pointer to member access operator ?: conditional operator sizeof size of object operator Operators that must be overloaded as members: = assignment operator [] subscript operator () function call operator -> indirect member access operator ->* indirect pointer to member access operator
One Argument Constructor and Operator Function A large range of classes are available in the class libraries with compiler. When the programmer makes an attempt to convert the built-in class data type to the user defined data type then errors are generated. To avoid this problem the programmer must define the routines that can perform this conversion. These routines are coded in the form of one argument constructor and operator function. As we have already discussed the conversion types, such as class to basic, basic to class and class to class are used.
Overloading Stream Operators The predefined objects cin and cout are used to perform various input/output operations in C++. The extraction operator (>>) is used with cin object to carryout input operations. The insertion operator (<<) is used with cout object to carry out output operations. It is possible to overload both these extraction and insertion operators with friend function.