next up previous
Next: Functions acting on classes Up: Simple Classes: mycomplex0.h Previous: Simple Classes: mycomplex0.h

Constructors

In the simple example above the complex class is only a container for holding the real and imaginary parts. The only thing we gain from it is a tidy packaging. In the following examples we improve on it.

First we introduce a way to automatically initialize the complex number when it is declared. A standard way to do this is as follows:

#include <iostream>

class complex {
public:
  double re;
  double im;

  // Constructors
  complex(){re = 0; im = 0;}
  complex(double r, double i = 0){re = r; im = i;}
};

In the main program we can then use the following declarations:

   complex a,b,z1(-1),z2(3.4,-2.);

The statement

  complex(){re = 0; im = 0;}
defines a special class function or "method" called a "constructor". The function definition is so short, it has been put on a single line. We can make it look more like the functions we have already seen by splitting it into a few lines this way:
  complex(){
    re = 0; 
    im = 0;
  }
but for short functions the one-line definition is easier to read. Remember, the compiler doesn't care how we break the lines.

Constructors are invoked at the time a class object is created (or in C++ jargon, ``instantiated''). The name of the constructor is the same as the name of the class. The datatype of the constructor is always the same as that of the class itself, so by convention in C++, we don't specify its type explicitly. The pair of empty parentheses indicates that this constructor takes no arguments. The assignment statements in braces say to set the real and imaginary parts to zero. This constructor is invoked by the declaration

  complex a;
which creates an instance of "complex" called a with zero real and imaginary parts.

A second constructor is also defined:

  complex(double r, double i = 0){re = r; im = i;}

This constructor is designed to take one or two arguments for initializing the complex number after it is created. With two arguments, the real part is set to the first argument and the imaginary part to the second. With one, the real part is set to the first (and only) argument and the imaginary part, to the specified default value 0. This constructor is invoked by the declaration

   complex z1(-1),z2(3.4,-2.);
which creates z1 with real part $-1$ and imaginary part zero and z2 with real part $3.4$ and imaginary part $-2$.

The complex constructor can also be used as a function with the more familiar function syntax:

   a = complex(4,-9);
   z1 = complex();
In this case the real part of a is set to $4$ and the imaginary part to $-9$, and the real and imaginary parts of z1 are set to zero. Notice that the assignment = here is for complex objects. For simple classes the compiler does the assignment in a natural way, i.e. all the data members are assigned, meaning in this case that the real part on the lhs is set equal to the real part on the rhs and the same for the imaginary parts. Later we will see that for more complicated classes we have to tell the compiler how to do the assignment.

As a function, complex takes zero, one, or two arguments of type double. This is an example of name "overloading" in C++. The context distinguishes them: The compiler counts the arguments and examines their types to tell them apart. The combination of function name and argument number and type is called the "signature" of the function. A function name can be overloaded as long as each new definition has a unique signature.

C++ provides similar constructors for the base types float, double, int, etc. For example, instead of the initialization

   double a = -3.5;
we could have written
   double a(-3.5);
and instead of
   double a;
   a = -3.5;
we could have written
   double a;
   a = double(-3.5);
Of course the simpler forms are preferable in most cases.


next up previous
Next: Functions acting on classes Up: Simple Classes: mycomplex0.h Previous: Simple Classes: mycomplex0.h
Carleton DeTar 2017-02-13