Constructors are a feature that make initialization of structures convenient. Within a structure type definition, define a constructor in a way that is similar to a function definition, with the following differences.
The name of the constructor must be the same as the name of the structure type.
Do not write a return type. The definition starts with the name of the constructor.
In the body of the constructor, refer to the fields by their names. Do not use a dot. The fields are implicitly those of the structure that is being initialized.
For example,
struct Cell { int item; const char* name; Cell(int it, const char* nm) { item = it; name = nm; } };defines type Cell with two fields and one constructor that takes two parameters.
You can use a constructor in three ways, which we illustrate for type Cell.
Cell c(20, "a cell");
This is equivalent to
Cell c; c.item = 20; c.name = "a cell";since the constructor definition's body says to do item = it; name = nm;where it and nm are the parameters. In general, writing parameters after a variable name in a statement that creates the variable runs the constructor with the given parameters after creating the variable. |
Cell* p = new Cell(20, "a cell");
Expression new Cell(it,nm) creates a new cell
in the heap and runs the constructor on that
new cell, with the given parameters. The expression's value
is a pointer to the new cell. Notice that,
in this case, the parameters are written after
new Cell, not after the name of the pointer
variable p.
Expression new Cell(it, nm) has type Cell*. |
Cell(20, "a cell");
Expression Cell(it, nm) creates a cell
in the frame of the current function and
initializes that cell.
Expression Cell(it, nm) has type Cell.
You will not find this form very useful. Be careful not to confuse it with new Cell(it, nm), which yields a pointer (type Cell*) to a new cell that is in the heap. You might be tempted to write Cell c = Cell(20, "a cell");That works, but it is clumsy. Just write Cell c(20, "a cell"); |
Field names
The presence of a constructor does not alter the names
of the fields. Type Cell above has two fields, called
item and name. It does not make sense to write
Cell c; c.it = 34;since a Cell does not have a field called it. The constructor happens to have a parameter called it. |
What to initialize in a constructor
It is good practice to ensure that
a constructor initializes all of the fields
of a structure. For example, the
constructor for Cell initializes both of the
fields, item and name.
It is not necessary for a constructor to have as many parameters as there are fields, but it often does. If you have fewer parameters than fields, you typically initialize some of the fields to default values. |
Multiple constructors
A structure type definition can include more
than one constructor, as long as no two constructors
have the same number and types of parameters. For
example, an alternative definition of type Cell
with three constructors is as follows.
struct Cell { int item; const char* name; Cell(int it, const char* nm) { item = it; name = nm; } Cell(int it) { item = it; name = ""; } Cell() { item = 0; name = ""; } }; |
Constructor requirement
If you define at least one constructor then
each time you create a structured value of that type
you must use one of the constructors. For
example,
Cell a(16, "kangaroo"); Cell b(3);uses the constructor with two parameters to create a and the constructor with one parameter to create b. |
Parameterless constructors
To use a parameterless constructor, do not
write ( ). For example,
Cell c;creates a Cell c and initializes it using the constructor with no parameters. Similarly, Cell* p = new Cell;creates a new Cell in the heap and initializes that cell using the parameterless constructor. Watch out. In C++, statement Cell d();does not create a Cell at all. It is interpreted as a prototype for a function called d. |
Constructors and arrays
If you create an array of a structure type,
then each thing in the array is automatically
initialized using the parameterless constructor.
For example,
Cell A[10];creates an array of Cell values and initializes each of them using the parameterless constructor. Note. If there is at least one constructor and no parameterless constructor then you are not allowed to create an array of structures of that type. Note. An array of pointers is not automatically initialized. So Cell* P[10];creates an array of uninitialized pointer variables. (The pointers are dangling until you store something into them.) |
Rewrite type Complex from the preceding page, providing two constructors: one takes two parameters of type double and installs them into the two fields; the other takes no parameters and sets both fields to 0.0. Answer
Using type Complex from the preceding exercise, write a statement that creates a new complex number whose real part is 1.0 and whose imaginary part is 2.5. Call the new complex number z, and put it in the frame for the current function. Answer
Repeat the previous exercise, but this time allocate the complex number in the heap, and make z a pointer to it. Answer
If you create an array of Complex values, how are the values in the array initialized? Answer
Write a statement that creates variable zero of type Complex. Initialize it using the parameterless constructor. Answer
A function is allowed to return a structure. Write a function that takes two complex numbers and returns their sum. Answer
Redo the preceding exercise, but make your function return a pointer to a Complex structure. Answer