7

CHAPTER

Constructors and
Destructors

C
H
A
P
T
E
R

O
U
T
L
I
N
E
—•    7.1 Introduction
—•    7.2 Constructors and Destructors
—•    7.3 Characteristics of Constructors and Destructors
—•    7.4 Applications with Constructors
—•    7.5 Constructors with Arguments
—•    7.6 Overloading Constructors
—•    7.7 Constructors with Default Arguments
—•    7.8 Copy Constructors
—•    7.9 The const Objects
—•  7.10 Destructors
—•  7.11 Calling Constructors and Destructors
—•  7.12 Qualifier and Nested Classes
—•  7.13 Anonymous Objects
—•  7.14 Private Constructors and Destructors
—•  7.15 Dynamic Initialization using Constructors
—•  7.16 Dynamic Operators and Constructors
—•  7.17 The main( ) as a Constructor and Destructor
—•  7.18 Recursive Constructor
—•  7.19 Program Execution before main( )
—•  7.20 Constructor and Destructor with Static Members
—•  7.21 Local vs Global Object

7.1 INTRODUCTION

When a variable is declared and if not initialized, it contains garbage value. The compiler itself cannot carry out the process of initialization of a variable. The programmer needs explicitly to assign a value to the variable. Initialization prevents the variable from containing garbage value.

Consider an example

  float height;   // variable declaration
  height=5.5;     // assigning value to variable

In the above example, height is a variable of float type. It holds any garbage value before initialization. In the next statement, variable height is initialized with 5.5.

C++ handles abstract data type, which is the combination of one or more basic data type. An object holds copies of one or more individual data member variables. When an object is created, its data member contains garbage value.

We learned in the last chapter that declaring static member variables facilitates programmer to initialize member variables with desired values. The drawback of static members is that only one copy of static member is created for entire class. All objects share the same copy, which do not provide security. And the main disadvantage of static object is that its value remains in the memory throughout the program.

7.2 CONSTRUCTORS AND DESTRUCTORS

In the last chapter, we defined a separate member function for reading input values for data members. Using object, member function is invoked and data members are initialized. The programmer needs to call the function. C++ provides a pair of in-built special member functions called constructor and destructor. The constructor constructs the objects and destructor destroys the objects. In operation, they are opposite to each other. The compiler automatically executes these functions. The programmer does not need to make any effort for invoking these functions.

The C++ run-time arrangement takes care of execution of constructors and destructors. When an object is created, constructor is executed. The programmer can also pass values to the constructor to initialize member variables with different values. The destructor destroys the object. The destructor is executed at the end of the function when objects are of no use or goes out of scope. It is optional to declare constructor and destructor. If the programmer does not define them, the compiler executes implicit constructor and destructor.

Constructors and destructors are special member functions. Constructors and destructors decide how the objects of a class are created, initialized, copied, and destroyed. Their names are distinguished from all other member functions because their name is same as the class they belong to. The only difference is that destructor is preceded by ~ (tilde) operator.

Constructors and destructors have many attributes as that of normal member functions. We can declare and define them within the class, or declare them within the class and define them outside, but they have few unique characteristics.

(1) Constructors

If a class B has one or more constructors, one of them is invoked each time when we define an object b of class B. The constructor creates object b and initializes it. Constructors are also called when local or temporary objects of a class are created.

Example

B( )  {     }

(2) Destructors

Destructors are opposite to the constructor. The process of destroying the class objects created by constructors is done in destructor. The destructors have the same name as their class, preceded by a tilde (~). A destructor is automatically executed when object goes out of scope. It is also invoked when delete operator is used to free memory allocated with class pointer. Like constructor, it is not possible to define overloaded destructor and passing arguments to them. The class can have only one destructor. Destructors are called when these objects go out of scope.

Example

~B( )   {        }

7.3 CHARACTERISTICS OF CONSTRUCTORS AND DESTRUCTORS

(1) Constructors

(1) Constructor has the same name as that of the class it belongs.

(2) Constructor is executed when an object is declared.

(3) Constructors have neither return value nor void.

(4) The main function of constructor is to initialize objects and allocate appropriate memory to objects.

(5) Though constructors are executed implicitly, they can be invoked explicitly.

(6) Constructor can have default and can be overloaded.

(7) The constructor without arguments is called as default constructor.

(2) Destructors

(1) Destructor has the same name as that of the class it belongs to and preceded by ~ (tilde).

(2) Like constructor, the destructor does not have return type and not even void.

(3) Constructor and destructor cannot be inherited, though a derived class can call the constructors and destructors of the base class.

(4) Destructors can be virtual, but constructors cannot.

(5) Only one destructor can be defined in the destructor. The destructor does not have any argument.

(6) The destructors neither have default values nor can be overloaded.

(7) Programmer cannot access addresses of constructors and destructors.

(8) TURBO C++ compiler can define constructors and destructors if they have not been explicitly defined. They are also called on many cases without explicit calls in program. Any constructor or destructor created by the compiler will be public.

(9) Constructors and destructors can make implicit calls to operators new and delete if memory allocation/ de-allocation is needed for an object.

(10) An object with a constructor or destructor cannot be used as a member of a union.

7.4 APPLICATIONS WITH CONSTRUCTORS

The initialization of member variables of class is carried out using constructors. The constructor also allocates required memory to the object. An example of constructor follows next.

class num
  {
    private:
    int a, b,c;

    public:

  num (void);   // declaration of constructor
  - - - - -
  - - - - -
  };

  num :: num (void)    // definition of constructor
  {
  a=0;b=0;c=0;            // value assignment
  }

main ( )
{

class num x;
}

In the above example, class num has three member integer variables a, b and c. The declaration of constructor can be done inside the class and definition outside the class. In definition, the member variables of a class num are initialized to zero.

In the function main( ), x is an object of type class num. When an object is created, its member variables (private and public) are automatically initialized to the given value. The programmer need not write any statement to call the constructor. The compiler automatically calls the constructors. If the programmer writes a statement for calling a constructor, a constructor is called again. If there is no constructor in the program, in such a case the compiler calls dummy constructor. The constructor without argument is called as default constructor.

7.1 Write a program to define a constructor and initialize the class data member variables with constants.

# include <iostream.h>
# include <conio.h>

class num
{

  private:
  int a,b,c;
  public:
  int x;

  num(void);  // declaration of constructor

  void show( )
  { cout <<"
 x = " <<x <<" a= " <<a <<" b= "<<b <<" c= "<<c; }
};

  num :: num (void)  // definition of constructor
    {
       cout <<"
 Constructor called";
       x= 5 ; a= 0 ;b = 1;c = 2;
    }
main( )
{
  clrscr( );
  num x;
  x.show( );
  return 0;
}

OUTPUT
Constructor called
x = 5 a= 0 b= 1 c= 2

Explanation: In the above program, the class num is declared with four integers a, b, c and x. The variables a, b and c are private and x is a public variable. The class also has show( ) function and constructor prototype declaration. The function show( ) displays the contents of the member variables on the screen. The definition of a constructor is done outside the class. In the function main( ), x is an object of class num. When an object is created, constructor is automatically invoked and member variables are initialized to given values as per the constructor definition. The values of variablesx, a, b and c are as per the output shown. The compiler calls the constructor for every object created. For each object the constructor is executed once i.e., the number of times of the execution of constructor is equal to the number of objects created. The program given below explains this point.

7.2 Write a program to show that for each object constructor is called separately.

# include <iostream.h>
# include <conio.h>
class num

{
  private:
  int a;

  public:
num (void)  // definition of constructor
  {
     cout <<"
 Constructor called.";
     a=1;
     cout<< " a = "<<a;
  }

};
main( )
{
  clrscr( );
  num x,y,z;

  num a[2];
  return 0;
}

OUTPUT:

Constructor called. a = 1

Constructor called. a = 1

Constructor called. a = 1

Constructor called. a = 1

Constructor called. a = 1

Explanation: In the above program, x, y and Z are objects of class num. A[2] is an array of objects. For each individual object constructor is called. The total number of objects declared are five; hence, the constructor is called five times.

7.3 Write a program to read values through the keyboard. Use constructor.

# include <iostream.h>
# include <conio.h>

class num
{
  private:
  int a,b,c;

  public:
  num(void);  // declaration of constructor

  void show( )
  {  cout <<"
"<<" a= " <<a <<" b= "<<b <<" c= "<<c; }
};
  num :: num (void)  // definition of constructor
    {
       cout <<"
 Constructor called";
       cout <<"
 Enter Values for a,b and c : ";
       cin >> a>>b>>c;
  }
main( )
{
  clrscr( );
  class num x;
  x.show( );

  return 0;
}

OUTPUT

Constructor called

Enter Values for a,b and c : 1 5 4

a= 1 b= 5 c= 4

Explanation: The above program is the same as the previous one. In this program, whenever an object is created, the constructor is called and it reads the integer values through the keyboard. Thus, entered constants are assigned to member variables of the class. Here, the constructor is used like other functions.

7.5 CONSTRUCTORS WITH ARGUMENTS

In the previous example, constructors initialize the member variables with given values. It is also possible to create constructor with arguments and such constructors are called as parameterized constructors. For such constructors, it is necessary to pass values to the constructor when object is created. Consider the example given next.

class num
  {
   private:
   int a, b, c;
   public:

num (int m, int j , int k) ;  // declaration of constructor with arguments
 - - - - -
 - - - - -
 };
 num :: num (int m, int j, int k)  // definition of constructor with arguments
 {
 a=m;
 b=j;
 c=k;
 }

main( )
{
class num x=num (4,5,7);  // Explicit call
class num y (9,5,7);      //  Implicit call
}

In the above example, the declaration and definition of a constructor contains three integer arguments. In the definition the three arguments m, j and k are assigned to member variables a, b and c.

In a situation like this when class has a constructor with arguments, care is to be taken while creating objects. So far, we created the object using the following statement:

num x

This statement will not work. We need to pass required arguments as per the definition of constructor. Hence, to create object the statement must be as given below:

(a) class num x=num (4,5,7);  // Explicit call
(b) class num y (9,5,7);      //  Implicit call

The statements (a) and (b) can be used to create objects, that not only create objects but also pass given values to the constructor. The method (a) is called as explicit call and the method (b) is called as implicit call.

7.4 Write a program to create constructor with arguments and pass the arguments to the constructor.

# include <iostream.h>
# include <conio.h>

    class num
    {
     private:
     int a,b,c;
     public:

num(int m, int j , int k) ;  // declaration of constructor with arguments

      void show( )
      {
      cout <<"
 a= "<<a <<" b= "<<b <<" c= "<<c;
      }
    };
num :: num (int m, int j , int k) // definition of constructor with arguments
{
  a=m;
  b = j ;
  c=k ;
}

main( )
{
  clrscr( );
  num x=num(4,5,7);  // Explicit call
  num y(1,2,8);      // Implicit call
  x.show( );
  y.show( );
  return 0;
}

OUTPUT

a= 4 b= 5 c= 7

a= 1 b= 2 c= 8

Explanation: In the above program, x and y are objects of class num. When objects are created, three values are passed to the constructor. These values are assigned to the member variables. The function show( ) displays the contents of member variables.

7.6 OVERLOADING CONSTRUCTORS

Like functions, it is also possible to overload constructors. In previous examples, we declared single constructors without arguments and with all arguments. A class can contain more than one constructor. This is known as constructor overloading. All constructors are defined with the same name as the class. All the constructors contain different number of arguments. Depending upon number of arguments, the compiler executes appropriate constructor. Table 7.1 describes object declaration and appropriate constructor to it. Consider the following example:

class num
  {
     private:
     int a;
     float b;
     char c;
     public:

(a) num (int m, float j , char k);
(b) num (int m, float j);
(c) num ( );
(d) class num x (4,5.5,‘A’);
(e) class num y (1,2.2);
(f) class num z;

Table 7.1 Overloaded constructors

Constructor declaration Object declaration
(a) num(int m, float j , char k);
(b) num(int m, float j);
(c) num( );
(d) num x(4,5.5,'A”);
(e) num y(1,2.2);
(f) num z;

In the above example, statements (a), (b) and (c) are constructor declarations and (d), (e) and (f) are the object declarations. The compiler decides which constructor to be called depending on number of arguments present with the object.

When object x is created, the constructor with three arguments is called because the declaration of an object is followed by three arguments. For object y, constructor with two arguments is called and lastly object Z, which is without any argument, is candidate for constructor without argument.

7.5 Write a program with multiple constructors for the single class.

# include <iostream.h>
# include <conio.h>

  class num
  {
    private:
    int a;

    float b;
    char c;

    public:
    num(int m, float j , char k);
    num (int m, float j);
    num( );

    void show( )
    {
    cout <<"
	 a= "<<a <<" b= "<<b <<" c= "<<c;
    }
};

num :: num (int m, float j , char k)
{
  cout <<"
 Constructor with three arguments";
  a=m;
  b=j;
  c=k;
}

num :: num (int m, float j)
{
  cout <<"
 Constructor with two arguments";
  a=m;
  b=j;
  c=‘ ’;
}

num :: num( )
{
  cout <<"
 Constructor without arguments";
   a=b=c=NULL;
}
main( )
{
  clrscr( );
  class num x(4,5.5,‘A’);

  x.show( );
  class num y(1,2.2);
  y.show( );
  class num z;
  z.show ( );
  return 0;
}

OUTPUT

Constructor with three arguments

  a= 4 b= 5.5 c= A

Constructor with two arguments

  a= 1 b= 2.2 c=

Constructor without arguments

  a= 0 b= 0 c=

Explanation: In the above program, three constructors are declared. The first constructor is with three arguments, second with two and third without any argument. While creating objects, arguments are passed. Depending on the number of arguments the compiler decides which constructor is to be called. In this program x, y and z are three objects created. The x object passes three arguments. The y object passes two arguments and z object passes no arguments. The function show( ) is used to display the contents of the class members.

7.7 CONSTRUCTORS WITH DEFAULT ARGUMENTS

Like functions, it is also possible to declare constructors with default arguments. Consider the following example.

power (int 9, int 3);

In the above example, the default value for the first argument is nine and three for second.

power p1 (3);

In this statement, object p1 is created and nine raise to 3 expression n is calculated. Here, one argument is absent hence default value 9 is taken, and its third power is calculated. Consider the example on the above discussion given below.

7.6 Write a program to declare default arguments in constructor. Obtain the power of the number.

# include <iostream.h>
# include <conio.h>
# include <math.h>

class power

{
     private:
     int num;
     int power;
     int ans;

     public :

power (int n=9,int p=3); // 
declaration of constructor with default argu- ments      void show( )      {         cout <<" "<<num <<" raise to "<<power <<" is " <<ans;      } };   power :: power (int n,int p )   {      num=n;      power=p;      ans=pow(n,p);   } main( ) {   clrscr( );   class power p1,p2(5);   p1.show( );   p2.show( );   return  0; }

OUTPUT
9 raise to 3 is 729
5 raise to 3 is 125

Explanation: In the above program, the class power is declared. It has three integer member variables and one member function show( ). The show( ) function is used to display the values of member data variables. The constructor of class power is declared with two default arguments. In the function main( ), p1 and p2 are two objects of class power. The p1 object is created without argument. Hence, the constructor uses default arguments in pow( ) function. The p2 object is created with one argument. In this call of constructor, the second argument is taken as default. Both the results are shown in output.

7.8 COPY CONSTRUCTORS

The constructor can accept arguments of any data type including user-defined data types and an object of its own class. Consider the examples given in Table 7.2.

Table 7.2 Copy constructors

Statement (a) Statement (b)
class num
{
private:
----
----
----
public:
num(num);
}
class num
{
private:
- - - -
- - - -
- - - -
public:
num(num…);
}

In statement (a) an argument of the constructor is same as that of its class. Hence, this declaration is wrong. It is possible to pass reference of object to the constructor. Such declaration is known as copy constructor. The statement (b) is valid and can be used to copy constructor.

When we pass an object by value into a function, a temporary copy of that object is created. All copy constructors require one argument, with reference to an object of that class. Using copy constructors, it is possible for the programmers to declare and initialize one object using reference of another object. Thus, whenever a constructor is called a copy of an object is created.

7.7 Write a program to pass an object with reference to constructor. Declare and initialize other objects.

# include <iostream.h>
# include <conio.h>

class num
{
    int n;
    public :

    num ( ) { }  // constructor without argument
    num (int k) { n=k;} // constructor with one argument

    num (num &j)  // copy constructor
    {
       n=j.n;
    }

void show (void) { cout <<n; }
};
main( )
{
  clrscr( );
  num J(50);
  num K(J);
  num L=J;
  num M;
  M=J;
cout <<"
 Object J Value of n : ";
J.show( );
cout <<"
 Object K Value of n : ";
K.show( );
cout <<"
 Object L Value of n : ";
L.show( );
cout <<"
 Object M Value of n : ";
M ,show( );
return 0;
}

OUTPUT

Object J Value of n : 50

Object K Value of n : 50

Object L Value of n : 50

Object M Value of n : 50

Explanation: In the above program, class num is declared with one integer member variable n and three constructors. In function main( ), the object J is created and 50 is passed to constructor. It is passed by value; hence, constructor with one argument is invoked. When object K is created with one object the copy constructor is invoked, object is passed, and data member is initialized. The object L is created with assignment with object J; this time also copy constructor is invoked. The compiler copies all the members of object J to destination object L in the assignment statement num L=J. When object is created without any value, like M, default constructor is invoked. The copy constructor is not invoked even if the object J is assigned to object M.

The data member variables that are dynamically allocated should be copied to the target object explicitly by using assignment statement or by copy constructor as per the given statement.

num L=J;  / / copy constructor is executed

Consider the statement

M=J;

Here, M and J is predefined object. In this statement, copy constructor is not executed. The member variables of object J are copied to object M member-by- member. An assignment statement assigns value of one entity to another.

The statement num L=J; initializes object L with J during definition. The member variables of J are copied member-by-member into object L. This statement invokes constructor. This statement can be written as num L (J), which we frequently use to pass values to the constructor.

7.9 THE const OBJECTS

In the last chapter, we have studied the constant functions. The const declared functions do not allow the operations that alter the values. In the same fashion, we can also make the object constant by the keyword const. Only constructor can initialize data member variables of constant object. The data members of constant objects can only be read and any effort to alter values of variables will generate an error. The data members of constant objects are also called as read only data members. The constant object can access only constant functions. If constant object tries to invoke a non-member function, an error message will be displayed.

7.8 Write a program to declare constant object. Also, declare constant member function and display the contents of member variables.

# include <iostream.h>
# include <conio.h>

class ABC
{
    int a;
    public :

    ABC (int m)
    { a=m; }
    void show ( ) const
    {  cout <<"a = "<<a; }
};

int main ( )
{
  clrscr( );
  const ABC x(5);
  x.show( );

return 0;
}

OUTPUT

A=5

Explanation: In the above program, class ABC is declared with one member variable and one constant member function show( ). The constructor ABC is defined to initialize the member variable. The show( ) function is used to display the contents of member variable. In main( ), the object x is declared as constant with one integer value. When object is created, the constructor is executed and value is assigned to data member. The object x invokes the member function show( ).

7.10 DESTRUCTORS

Destructor is also a special member function like constructor. Destructors destroy the class objects created by constructors. The destructors have the same name as their class, preceded by a tilde (~).

For local and non-static objects, the destructor is executed when the object goes out of scope. In case the program is terminated by using return or exit( ) statements, the destructor is executed for every object existing at that time. It is not possible to define more than one destructor. The destructor is only one way to destroy the object. Hence, they cannot be overloaded.

A destructor neither requires any argument nor returns any value. It is automatically called when object goes out of scope. Destructor releases memory space occupied by the objects.

The program given below explains the use of destructor.

7.9 Write a program to demonstrate execution of constructor and destructor.

# include <iostream.h>
# include <constream.h>

struct text
{
    text( ) // Constructor
 {
    cout <<"
 Constructor executed.";
 }

 ~text( ) // Destructor
 {
    cout <<"
 Destructor executed.";
 }

};

void main( )
 {
   clrscr ( );
   text t;  // Object declaration
}

OUTPUT

Constructor executed.

Destructor executed.

Explanation: In the above program, the class text contains constructor and destructor. In function main( ), object t is executed. When object t is declared, constructor is executed. When object goes out of scope, destructor is executed.

7.10 Write a program to create an object and release them using destructors.

# include <iostream.h>
# include <conio.h>

int c=0; // counter for counting objects created and destroyed.

class num
{
    public :

    num( )
    {
    c++;
    cout <<"
 Object Created : Object("<<c <<")";
    }

    ~num( )
    {
      cout <<"
 Object Released : Object("<<c <<")";
    c-- ;
    }
};

main( )
{
  clrscr( );

  cout <<"
 In main( ) 
"; num a,b;
  cout <<"

 In Block A
";
{
  class num c;
}
cout <<"

 Again In main( )
";
return 0;
}

Output

In main( )

Object Created : Objecte(1)

Object Created : Object (2)

In Block A

Object Created : Object(3)

Object Released : Object(3)

Again In main( )

Object Released : Object (2)

Object Released : Object(1)

Explanation: In the above program, the variable c is initialized with zero. The variable c is incremented in constructor and decremented in destructor. When objects are created the compiler calls the constructor. Objects are destroyed or released when destructor is called. Thus, the value of a variable changes as the constructors and destructors are called. The value of a variable of c shows number of objects created and destroyed. In this program the object a and b are created in main( ). The object c is created in another block i.e., in block A. The object c is created and destroyed in the same block. The objects are local to the block in which they are defined. The object a and b are released as the control passes to main( ) block. The object created last is released first.

7.11 CALLING CONSTRUCTORS AND DESTRUCTORS

The compiler automatically calls the constructor and destructor. We can also call the constructor and destructor in the same fashion as we call the normal user-defined function. The calling methods are different for constructors and destructors. In practice, it may not be useful but for the sake of understanding, few examples are illustrated on this concept.

7.11 Write a program to invoke constructor and destructor.

# include <iostream.h>
# include <conio.h>
class byte
{
    int bit;
    int bytes;

    public :

    byte( )
    {
       cout <<"
 Constructor invoked";
       bit=64;
       bytes=bit/8;
    }

    ~byte( )
    {
       cout <<"
 Destructor invoked ";
       cout <<"
 Bit = "<<bit;
       cout <<"
 Byte = "<<bytes;
    }
};

int main ( )
{
    clrscr( );
    byte x;
    byte( );            // calling constructor

    // x.byte( ) ;      // invalid statement
    // x.byte::byte( )  // valid statement
    // ~ byte( );       // invalid statement
    // byte.~byte( );   // invalid statement
    // x.~byte( );      // Member identifier expected

    x.byte::~byte( );

    return 0;
}

OUTPUT

Constructor invoked

Constructor invoked
Destructor invoked
Bit = 64
Byte = 8
Destructor invoked
Bit = 64
Byte = 8
Destructor invoked
Bit = 64
Byte = 8

Explanation: In the above program, the class byte is declared with two integer members. The class has constructors and destructors. In function main( ), x is an object of class byte. When an object is created the compiler automatically invokes the constructor. The program also invokes constructor. Thus, constructor is executed twice i.e., implicitly and explicitly. The constructor is called without the help of object of that class. If we try to call the constructor with the help of object x as per the statement x.byte( ), the compiler displays an error message.

The destructor cannot be invoked like constructor. Calling destructor requires the help of object and class name. Only object of the class alone is not able to invoke the destructor, the object needs help of the class. The statement x. ~byte( ) is invalid, the compiler displays the error message Member identifier expected. The destructor can be invoked using the statement x.byte::~byte( ). Here, class name is also specified.

The constructor and destructor can call each other. The statement byte::byte( ) is used for calling destructor ~byte( ) within the body of constructor byte( ). The destructor ~byte( ) can call the constructor byte( ) using the statement byte( ). The constructor and destructor may contain condition statements; such destructors or constructors are called as conditional constructor or conditional destructor. The conditional constructor can be created using if-else or switch( ) statements. The example given below illustrates this.

7.12 Write a program to define conditional constructor and destructor.

# include <iostream.h>
# include <conio.h>
int c=0;

class byte

{
     int bit;
     int bytes;
     public :

     ~byte( );  // Prototype declaration

     byte ( )
     { cout <<"
 Constructor invoked";
       bit=64;
       bytes=bit/8;
       byte:: ~byte( );   // call to destructor
     }
  };

  byte::~byte( )
     {
     if (c==0)
     {
     // byte( ) //  call to constructor
     cout <<"
 Destructor invoked ";
     cout <<"
 Bit  = "<<bit;
     cout <<"
 Byte = "<<bytes;
     }
     c++;
  }

int main( )
{    clrscr( );
     byte x,y;
     return 0;
}

OUTPUT
Constructor invoked
Destructor invoked
Bit = 64
Byte = 8
Constructor invoked

Explanation: In the above program, x and y are objects of class byte. The compiler automatically invokes the constructor. The constructor invokes the destructor. The variable c is declared and initialized with zero. It is a global variable declared before main( ) and can be used anywhere in the program. The destructor contains conditional statement if. The if block is executed only when c is zero. When first time destructor is called, the if block is executed and c is turned to non-zero value. Next time when destructor is called the if condition evaluates false and the if block is not executed. Though destructor is called, no result is displayed on the screen. Remember the constructors and destructors are executed for equal number of times. It is possible for the programmer to use the constructor and destructor like other user-defined functions.

7.12 QUALIFIER AND NESTED CLASSES

The class declaration can also be done inside the other class. While declaring object of such class, it is necessary to precede the name of the outer class. The name of outer class is called as qualifier name and the class defined inside is called as nested class.

The use of nested classes enhances the power of abstract data type and helps to construct more powerful data structure. The qualifier (host class) and nested class follow the same access conditions. The nested classes are useful to hide particular class and its objects within a qualifier class. The following program illustrates this.

7.13 Write a program to declare classes within classes and access the variables of both the classes.

# include <iostream.h>
# include <constream.h>

class A         // Host class or qualifier class
{
  public :
  int x;

  A ( ) {   x=10;    }

class B          // Nested class
{
  public:
  int y;

  B( ) { y=20; }

void show( )
{

  A a;
  cout <<"x="<<a.x<<ndl;
  cout <<"y="<<y<<endl;
}

};    // End of nested (inner) class

};   // End of qualifier (outer) class

void main( )
{
  clrscr( );
  A::B b;
  b.show( );
}

OUTPUT

x=10

y=20

Explanation: In the above program, the class B is declared inside the class A. All the members of both the classes are declared public so that they can be easily accessed. Both the classes have constructors to initialize the member variables. The class B also has one member function show( ) to display the contents on the screen.

In function main( ), A::B b declares object of class B. The name of class A is preceded because the class B is inside the class A. If we declare an object using the statement B b the program will be executed with a warning message “Use qualified name to access nested type ‘A::B’”. Here, the class A acts as a qualified class.

The show( ) function is a member of class B. Due to this variable y is its member variable and can be directly accessed. To access the variable of a qualified class A, object of class A a is declared and through this object variable x is accessed. The data variables are public. In case private, we can access member variables using member functions. There is no limit for declaring classes within classes. The following program explains this.

7.14 Write a program to declare multiple qualifier classes and declare an object of every class.

# include <iostream.h>
# include <conio.h>

class A
{

     public:
     int x;
     A( ) { x=5;
       cout <<" x= "<<x;
     }

       class B
       {
         public :
         int y;
         B( )
         {
         y=10;
         cout <<" y ="<<y;
         }

       class C
       {
         public :
         int z;
         C( )
         {
         z=15;
         cout <<" z ="<<z;
         }
     };
     };
     };

void main( )
{
  clrscr( );

  A a;             // outer class object
  A::B b;        //  middle class object
  A::B::C c;     //  inner class object
}

OUTPUT

x= 5 y =10 z =15

Explanation: In the above program, classes A, B and C are declared. The class B is declared inside the class A. The class C is declared inside the class B. A and B are qualified classes for class C. The class A is qualified class for class B. Each class has a constructor that initializes and displays the contents of the object.

7.13 ANONYMOUS OBJECTS

Objects are created with names. It is possible to create objects without name and such objects are known as anonymous objects. When constructors and destructors are invoked, the data members of the class are initialized and destroyed respectively. Thus, without object we can initialize and destroy the contents of the class. All these operations are carried out without object or we can also assume that the operations are carried out using an anonymous object, which exists but is hidden. The second thought is correct because if we apply pointer this (explained in Chapter “Pointers and Arrays”) we get the address of the object. It is not possible to invoke member function without using objects but we can invoke special member functions constructors and destructors which compulsorily exist in every class. Thus, without use of constructor and destructor the theory of anonymous object cannot be implemented in practical. Consider the following example.

7.15 Write a program to create anonymous object. Initialize and display contents of member variables.

# include <conio.h>
# include <iostream.h>

class noname
{
   private :
   int x;
   public:

   noname (int j)
   {
       cout <<"
 In constructor";
       x=j;
     show( );
     }
   noname ( )
   {
     cout <<"
 In constructor";
     x=15;
     show( );

   }
   ~noname( ) { cout <<"
 In destructor "; }
   noname *const  show( )
   {
   cout <<endl<<" x : "<<x;
   return this;
   }

};

void main( )
{
   clrscr( );
   noname( );
   noname(12);
}

OUTPUT

In constructor
x:15
In destructor
In constructor
x:12
In destructor

Explanation: In the above program, class noname is declared with one integer data member. The class also has constructor, destructor, and member function. The member function show( ) is used to display the contents on the screen.

In function main( ), no object is created. The constructor is called directly. Calling constructor directly means creating anonymous objects. In first call of the constructor, the member variable is initialized with 15. The constructor invokes the member function show( ) that displays the value of x on the screen.

It is not possible to create more than one anonymous object at a time. When constructor execution ends, destructor is executed to destroy the object. Again, the constructor with one argument is called and integer is passed to it. The member variable is initialized with 12 and it is displayed by show( ) function. Finally, the destructor is executed that marks the end of program.

TIP

Calling constructors directly means creating anonymous objects.

7.14 PRIVATE CONSTRUCTORS AND DESTRUCTORS

We know that when a function is declared as private, it could be invoked by the public function of the same class. So far, we’ve declared constructors and destructors as public. The constructor and destructor can be declared as private. The constructor and destructor are automatically executed when an object is executed and when an object goes out of scope. Nevertheless, when the constructors and destructors are private, they cannot be executed implicitly, and hence, it is a must to execute them explicitly. The following program is illustrated concerning this.

7.16 Write a program to declare constructor and destructor as private and call them explicitly.

# include <conio.h>
# include <iostream.h>

class A
{
  private:
  int x;

  ~A( ) { cout <<"
 In destructor ~A( )"; }

  A( )  {x=7;  cout <<"
 In constructor A( )"; }

  public:

  void show( )
  {
     this->A::A( ); // invokes constructor
     cout <<endl<<" x = "<<x;
     this->A::~A( );  // invoke destructor
  }

};

void main( )
{
  clrscr( );
  A *a;
  a->show( );
}

OUTPUT

In constructor A( )

x = 7

In destructor ~A( )

Explanation: In the above program, class A is declared. It has one data member, constructor, and destructor. The function show( ) is declared in public section. In function main( ), a is a pointer to class A. When pointer object is created, no constructor is executed. When show( ) function is invoked, the constructor is invoked and its return value is assigned to pointer *this. Every member function holds this pointer that point to the calling object. Here, the pointer points to object a. When the pointer invokes the constructor, constructor is invoked. Consider the statement this=this->A::A( ). The statement invokes the zero argument constructors. The contents is displayed by the cout statement and again the this pointer invokes the destructor.

7.15 DYNAMIC INITIALIZATION USING CONSTRUCTORS

After declaration of the class data member variables, they can be initialized at the time of program execution using pointers. Such initialization of data is called as dynamic initialization. The benefit of dynamic initialization is that it allows different initialization modes using overloaded constructors. Pointer variables are used as argument for constructors. The following example explains dynamic initialization using overloaded constructor.

7.17 Write a program to initialize member variables using pointers and constructors.

# include <iostream.h>
# include <conio.h>
# include <string.h>

class city
{
  char city[20];
  char state[20];
  char country[20];

public:

city( ) {    city[0]=state[0]=country[0]=NULL; }

void display( char *line);

city(char *cityn)
{

strcpy(city, cityn);
state[0]=NULL;
}

city(char *cityn,char *staten)
{
  strcpy(city,cityn);
  strcpy(state,staten);
  country[0]=NULL;
}

city(char *cityn,char *staten, char *countryn)
{
  _fstrcpy(city,cityn);
  _fstrcpy(state,staten);
  _fstrcpy(country,countryn);
}
};

void city:: display (char *line)
{
  cout <<line<<endl;
  if (_fstrlen(city))     cout<<"City    : "<<city<<endl;
  if (strlen(state))    cout <<"State   : "<<state <<endl;
  if (strlen(country))  cout <<"Country : "<<country <<endl;
}

void main( )
{
  clrscr( );
  city c1("Mumbai"),
       c2("Nagpur","Maharashtra"),
       c3("Nanded","Maharashtra","India"),
       c4('','',''),

  c1.display("=========*=============");
  c2.display("=========*============");
  c3.display("=========*============");
  c4.display("=========*=============");
}

OUTPUT

=========*=============

City : Mumbai

=========*=============

City : Nagpur

State : Maharashtra

=========*=============

City : Nanded

State : Maharashtra

Country : India

=========*=============

Explanation: In the above program, the class city is declared with three-character arrays city, state and country. The class city also has four constructors. They are zero-argument constructor, one argument constructor, two-argument constructor, and three-argument constructor. The display ( ) member function is used to display the contents on the screen.

In function main( ), c1, c2, c3 and c4 are declared and strings are passed. According to the number of arguments, respective constructors are executed. The function display( ) is called by all the four objects and information displayed is as per shown in the output. While calling function display( ), the line format “=====” is passed which is displayed before displaying the information. The display( ) function also contains if statements that checks the length of the string and displays the string only when the variable contains string. In case the data variable contains NULL, the string will not be displayed. The object c4 is initialized with NULL character. The use of c4 object is only to display line at the end of program.

7.16 DYNAMIC OPERATORS AND CONSTRUCTORS

When constructors and destructors are executed they internally use new and delete operators to allocate and de-allocate memory. The dynamic construction means allocation of memory by constructor for objects and dynamic destruction means releasing memory using the destructor. Consider the following program that explains the use of new and delete operator with constructors and destructors.

7.18 Write a program to use new and delete operators with constructor and destructor.

Allocate memory for given number of integers. Also release the memory.

# include <iostream.h>
# include <conio.h>

int number (void);

class num
{
    int *x;

    int s;
    public :

  num( )
  {
     s=number( );
     x= new int [s];
  }

  ~num( ) {  delete x;   }

  void  input( );
  void  sum( );

};

void num :: input( )
{
     for ( int h=0;h<s;h++)
  {
     cout <<"Enter number  ["<<h+1<< "] : ";
     cin>>x[h];
  }
}

void  num :: sum( )
{
int adi=0;
for ( int h=0;h<s;h++)
adi+=x[h];
cout <<" sum of elements = "<<adi;
}

number( )
{
  clrscr( );
  int n;
  cout <<" How many numbers : ";
  cin>>n;
  return n;

}

void main( )
{
  num n1;
  n1.input( );
  n1.sum( );
}

OUTPUT
How many numbers : 3
Enter number [1] : 1
Enter number [2] : 4
Enter number [3] : 5
sum of elements = 10

Explanation: In the above program, class num is declared with two variables and they are integer pointer *x and integer variable s. The class also contains constructor and destructor. The responsibility of constructor is to allocate memory using new operator for given number of integers by the user. The non-member function number( ) is used to input number of elements through the keyboard and entered numbers are stored in the variable s. The variable s is used with the new operator to allocate memory. The memory is allocated to the pointer x.

The member function input( ) reads elements and the for loop repeats the statement cin>>x[h] for s (number of total elements) times. The x[h] is used like array. The x is the starting address and h indicates the successive locations. The address of pointer x remains unchanged. The value of h is added to value of x. In this way, all these numbers are stored in continuous memory locations. If you are still confused as to how successive memory locations are accessed, go through the pointer arithmetic operations.

The sum( ) function is used to perform addition of all the entered numbers and displays the same on the screen. The destructor is finally executed which releases the memory using delete operator.

TIP

In the above program, if we remove the operators new and delete, the program will work successfully. However, this is suitable for small programs, developed for demonstration purpose. In real application, it needs large amount of memory to be allocated or released. It is very essential to check the memory before doing the process. For example, when any program is loaded in the memory, the operating system checks that available system resources are enough and not to load the requested application by the user. If memory is insufficient, compiler displays some error messages to the user.

7.17 THE main( ) AS A CONSTRUCTOR AND DESTRUCTOR

The constructors and destructors have the same name as their class. To use main( ) as a constructor and destructor we need to define class with the name main. So far, we have declared objects of classes without using the keyword class or struct because C++ treats classes like built-in data types. The use of keyword class or struct is only compulsory when the class name is main. This is because execution of program starts with the function main( ). The following program clears this point.

7.19 Write a program to declare class with name main.

# include <conio.h>
# include <iostream.h>

class main
{
  public:

main( ) { cout <<"
 In constructor main ( )"; }


~main( )  { cout <<"
 In destructor main ( )";   }

};


void main( )
{
  clrscr( );
  class  main  a;
}

OUTPUT In constructor main ( )
In destructor main ( )

Explanation: In the above program, the class is declared with the name main. Hence, it is compulsory to use keywords class or struct while declaring objects.

TIP

When the class name is main, it is compulsory to use keyword class or struct to declare objects.

7.18 RECURSIVE CONSTRUCTOR

Like normal and member functions, constructors also support recursion. The program given next explains this.

7.20 Write a program to invoke constructor recursively and calculate the triangular number of the entered number.

# include <iostream.h>
# include <conio.h>
# include <process.h>

class tri_num
{
  int f;
  public :

tri_num( ) { f=0; }


void sum( int j) {   f=f+j;  }

tri_num(int m)
{
        if (m==0)
        {
          cout <<"Triangular number : "<<f;
          exit(1);
        }

     sum(m);
     tri_num::tri_num(--m);
}

  };

void main( )
{
clrscr( );

tri_num a;
a.tri_num::tri_num(5);
}

OUTPUT
Triangular number : 15

Explanation: In the above program, class tri_num is declared with private integer f and member function sum( ). The class also has zero-argument constructor and one–argument constructor.

In function main( ), a is an object of tri_num class. When object a is declared, the zero–argument constructor is executed. The object a invokes the constructor explicitly and passes integer value to it. The passed value is received by the variable m of the constructor. The if statement checks the value of variable m and if it is zero the triangular number is displayed and program is terminated.

The sum( ) function is called by the constructor and cumulative sum is calculated and stored in the member variable f. Followed by the call of function sum( ), the constructor tri_num( ) is executed and the value of m is decreased by one. Thus, recursion takes places and each time value of m decreases. When the value of m becomes zero, the program terminates. We get the triangular number.

TIP

Recursion is very useful hence readers are requested to make it more clear by stepwise executing the program, in a single step. This will clear the flow of program. First, try the recursion with normal function in C style and after perfect understanding try with member function and constructors, but do not drop it.

7.19 PROGRAM EXECUTION BEFORE main ( )

It is impossible to execute a program without main( ). The declaration of objects is allowed before main( ). We know that when an object is created constructors and destructors are executed. The constructor can call other member functions. When an object is declared before main( ) it is called as global object. For global object constructor is executed before main( ) function and destructor is executed after the completion of execution of main( ) function. The following program illustrates this.

7.21 Write a program to declare global object and observe execution of constructor.

# include <iostream.h>
# include <constream.h>

  struct  text
  {
     text( )    // Constructor
     {
       cout <<"
 Constructor executed.";
     }

  ~text( )  // Destructor
  {
     cout <<"
 Destructor executed.";

  }

};

  text t;     // Global object
void main( )
{   }

OUTPUT

Constructor executed.

Destructor executed.

Explanation: In the above program, object t is declared before main( ). It is a global object. As soon as an object is declared, its constructor is invoked immediately. However, the execution of every program starts from function main( ), but for the object declared before main( ), constructor is executed before execution of main( ). The destructor for such object is executed after the complete execution of function main( ). The constructor can invoke other member functions. These member functions are also executed before main( ). Following program explains this.

7.22 Write a program to declare object before main( ) and invoke member function.

# include <iostream.h>
# include <conio.h>

class A
{
  private:
  char *y;
  int  x;

  public :

  A( )
  {
  clrscr( );
     cout <<"
 In constructor ";
     x=15;
  show( );   // invokes member function
  }

  void show( ) { cout<<endl<<" In show( )  x="<<x; }

  ~A( ) { cout<<endl<<" In destructor"; }

};
A a;

void main( ) { }

OUTPUT

In constructor
In show ( ) x=15
In destructor

Explanation: In the above program, class A is declared with member variable character pointer and integer x. The class also has constructor, destructor and member function show( ). Before main( ), object a is declared and constructor is executed that initializes the member variables. The constructor invokes the member function show( ). Finally, the destructor is executed.

7.20 CONSTRUCTOR AND DESTRUCTOR WITH STATIC MEMBERS

Every object has its own set of data members. When a member function is invoked, only copy of data member of calling object is available to the function. Some times it is necessary for all the objects to share data fields which is common for all the objects. If the member variable is declared as static, only one copy of such member is created for entire class. All objects access the same copy of static variable. The static member variable can be used to count number of objects declared for a particular class. The following program helps you to count number of objects declared for a class.

7.23 Write a program to declare static member variable. Count number of objects created and destroyed.

# include <iostream.h>
# include <constream.h>

class man
{
  static int no;

  char name;
  int age;

  public :
  man( )
  {
  no++;
  cout <<"
 Number of Objects exist: "<<no;
  }
  ~ man( )
  {
      --no;
      cout <<"
 Number of objects exist : "<<no;

  }

};

int man:: no=0;

void main( )
{
  clrscr( );

  man A,B,C;
  cout <<"
 Press any key to destroy object ";
  getch( );
}

OUTPUT

Number of Objects exist: 1
Number of Objects exist: 2
Number of Objects exist: 3
Press any key to destroy object
Number of objects exist: 2
Number of objects exist: 1
Number of objects exist: 0

Explanation: In this program, the class man has one static data member no. The static data member is initialized to zero. Only one copy of static data member is created and all objects share the same copy of static data member.

In function main( ), objects A, B and C are declared. When objects are declared constructor is executed and static data member no is increased with one. The constructor also displays the value of no on the screen. The value of static member shows us the number of objects present. When the user presses a key, destructor is executed, which destroys the object. The value of static variable is decreased in the destructor. The value of static member variable shows number of existing objects.

7.21 LOCAL vs GLOBAL OBJECT

The object declared outside all function bodies is known as global object. All functions can access the global object. The object declared inside a function body is known as local object. The scope of local object is limited to its current block.

When global and local variables are declared with the same name, in such a case the scope access operator is used to access the global variable in the current scope of local variable. We know that the local variable gets first precedence than global variable. The same is applicable for objects. When a program contains global and local objects with the same name, the local object gets first preference in its own block. In such a case, scope access operator is used with global object. The following program illustrates this.

7.24 Write a program to show the difference between local and global object.

# include <iostream.h>
# include <constream.h>

  class  text
  {
  public:

  void show (char *c)
  {
     cout <<"
"<<c;
  }

  };

text t;   // global object  declaration

void main( )
{
  text t;      // local object declaration
  ::t.show("Global");  // call using global object
  t.show("Local");    // call using local object
}

OUTPUT
Global
Local

Explanation: In the above program, the object t is declared in local as well as global scope. In function main( ), using scope access operator and t, the function show( ) is invoked. The first time function show( ) is invoked using global object. The second call to function show( ) is made by local object. The local object does not require scope access operator. The scope access operator is used only when the same name for object is used in global and local scopes. If scope access operator is not used before object, for both times function show( ) is invoked by local object.

SUMMARY

(1) C++ provides a pair of in-built functions called constructors and destructors. The compiler automatically executes these functions. When an object is created constructor is executed. The programmer can also pass values to the constructor to initialize member variables with different values. The destructor destroys the object. It is executed at the end of program when objects are of no use.

(2) Constructors and destructors decide how the objects of a class are created, initialized, copied, and destroyed. They are member functions. Their names are distinguished from all other member functions because they have the same name as the class they belong to.

(3) It is also possible to create constructor with arguments like normal functions.

(4) Like functions, it is also possible to overload constructors and assign default arguments.

(5) When we pass an object by value into a function, a temporary copy of that object is created. All copy constructors require one argument, with reference to an object of that class. Using copy constructors, it is possible for the programmers to declare and initialize one object using reference of another object. Thus, whenever a constructor is called a copy of an object is created.

(6) We can also make the object constant by the keyword const. Any effort to alter values of variables made by it will generate an error. The constant object can access only constant functions.

(7) The compiler automatically calls the constructor and destructor. We can also call the constructor and destructor in the same fashion as we call the normal user-defined function. The calling methods are different for constructors and destructors.

(8) Objects are created with names. It is not possible to declare objects without name. Such objects are known as anonymous objects.

(9) When the constructor and destructor are private, they cannot be executed implicitly. Hence, it is a must to execute them explicitly.

(10) We can also call the constructor and destructor in the same fashion as we call the normal user–defined function.

(11) The class declaration can also be done inside the other class. While declaring object of such class, it is necessary to precede the name of the outer class. The name of outer class is called as qualifier name and the class defined inside is called as nested class.

(12) The dynamic construction means allocation of memory by constructor for objects and dynamic destruction means releasing memory using the destructor.

(13) To use main( ) as a constructor and destructor we need to define class with the name main.

(14) Like normal and member functions, constructors also support recursion.

(15) For global objects constructor is executed before main( ) function and destructor is executed after the completion of execution of main( ) function.

(16) The object declared outside all function bodies is known as global object. All functions can access the global object. The object declared inside a function body is known as local object.

EXERCISES

[A] Answer the following questions.

(1) What are constructors and destructors?

(2) Explain the characteristics of constructors and destructors?

(3) Explain constructors with arguments. How are arguments passed to the constructor?

(4) What do you mean by overloading of constructors? How does it benefit the programmer?

(5) Explain constructor with default arguments?

(6) What is copy constructor?

(7) What are constant objects? How they are declared?

(8) How are constructors and destructors called explicitly?

(9) What is the difference between calling methods for constructor and destructor?

(10) Is it possible for a constructor and destructor to call each other?

(11) What are conditional constructors and destructors?

(12) What is anonymous object?

(13) What are nested and qualifier classes?

(14) What is the difference between local object and global object?

(15) What is static object? How is it different from normal object?

(16) How are private constructors and destructors executed?

(17) How will you declare constant object?

(18) What is default constructor?

(19) What is parameterized constructor?

(20) Explain negative aspect of static objects.

(21) What are local and global objects?

[B] Answer the following by selecting the appropriate option.

(1) Constructors and destructors are automatically invoked by

(a) compiler

(b) operating system

(c) main( ) function

(d) object

(2) Constructor is executed when

(a) object is declared

(b) object is destroyed

(c) both (a) and (b)

(d) none of the above

(3) The destructor is executed when

(a) object goes out of scope

(b) when object is not used

(c) when object contains nothing

(d) none of the above

(4) When memory allocation is essential, the constructor makes implicit call to

(a) new operator

(b) malloc( )

(c) memset( )

(d) random access memory

(5) Destructors can be

(a) overloaded

(b) of any data type

(c) able to return result

(d) explicitly called

(6) Constructor has the same name as

(a) the class they belong to

(b) the current program file name

(c) class name and preceded by ~

(d) both (a) and (c)

(7) The following program displays

# include <iostream.h>
class A
{
   int x;
   public:
   A( ) {x=10;}
   ~A( ) {}
};

void main ( )
{
   A a;
   cout<<(unsigned)a.A::A( ); }

(a) address

(b) value

(c) both (a) and (b)

(d) none of the above

(8) The following program returns address of

# include <iostream.h>

class A
{  public:
   A( ) {} ~A( ) {}
   A *display ( )   {      return (&A( ));   }   };

void main ( )
{
  void *p;
  clrscr( );
  A a;
  p=a.display( );
  cout <<p;
}

(a) constructor

(c) first element if any

(b) display ( )

(d) none of the above

[C] Attempt the following programs.

(1) Write a program to declare a class with private data members. Accept data through constructor and display the data with destructor.

(2) Write a program to pass an object to constructor and carry out copy constructor. Display contents of all the objects.

(3) Write a program to declare a class with three data members. Declare overloaded constructors with no arguments, one argument, two arguments, and three arguments. Pass values in the object declaration statement. Create four objects and pass values in such a way that the entire four constructors are executed one by one. Write appropriate messages in constructor and destructor so that the execution of the program can be understood.

(4) Write a program to declare a class with two data members. Also, declare and define member functions to display the content of the class data members. Create object A. Display the contents of object A. Again initialize the object A using explicit call to constructor. This time pass appropriate values to constructor. Display the contents of object A using member function.

(5) Write a program to call constructor recursively. Calculate factorial of a given number.

(6) Write a program to create array of strings. Read and display the strings using constructor and destructor. Do not use member functions.

(7) Write a program to create object without name.

(8) Write a program to declare global and local objects with the same name. Access member functions using both the objects?

[D] Find errors in the following programs.

(1)

class text
{  text ( )   { cout<<" Start";    }
   ~text ( )    {   cout <<"
 End"; }  };

void main  ( )   { text t; }

(2)

struct text
{public:

text (char *c)
{  cout <<"
"<<c; } };

void main ( ) { text t; }

(3)

class text
{  char *c;
   public:

text (*c) {  cout <<"
"<<c; } };

void main ( ) { text t("I WON"); }
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.146.176.145