Professional C__ - Marc Gregoire [80]
{
mValue = 0;
mString = "";
}
C++ provides an alternative method for initializing data members in the constructor, called the constructor initializer or ctor-initializer. Here is the 0-argument SpreadsheetCell constructor rewritten to use the ctor-initializer syntax:
SpreadsheetCell::SpreadsheetCell() : mValue(0), mString("")
{
}
Code snippet from SpreadsheetCellDefaultCtor\SpreadsheetCellInitList.cpp
As you can see, the ctor-initializer appears syntactically between the constructor argument list and the opening brace for the body of the constructor. The list starts with a colon and is separated by commas. Each element in the list is an initialization of a data member using function notation or a call to a superclass constructor (see Chapter 8).
Initializing data members with a ctor-initializer provides different behavior than does initializing data members inside the constructor body itself. When C++ creates an object, it must create all the data members of the object before calling the constructor. As part of creating these data members, it must call a constructor on any of them that are themselves objects. By the time you assign a value to an object inside your constructor body, you are not actually constructing that object. You are only modifying its value. A ctor-initializer allows you to provide initial values for data members as they are created, which is more efficient than assigning values to them later. Interestingly, the default initialization for strings gives them the empty string; so explicitly initializing mString to the empty string as shown in the preceding example is superfluous.
If your class has as data member an object without a default constructor, you have to use the ctor-initializer to properly construct that object. For example, take the following SpreadsheetCell class:
class SpreadsheetCell
{
public:
SpreadsheetCell(double d);
};
This class only has one explicit constructor accepting a double and does not include a default constructor. You can use this class as a data member of another class as follows:
class SomeClass
{
public:
SomeClass();
protected:
SpreadsheetCell mCell;
};
And implement the SomeClass constructor as follows:
SomeClass::SomeClass() { }
However, with this implementation, the following line will not compile. The compiler does not know how to initialize the mCell data member of SomeClass because it does not have a default constructor.
SomeClass s;
The solution is to initialize the mCell data member in the ctor-initializer as follows:
SomeClass::SomeClass() : mCell(1.0) { }
Ctor-initializers allow initialization of data members at the time of their creation.
Some programmers prefer to assign initial values in the body of the constructor. However, several data types must be initialized in a ctor-initializer. The following table summarizes them:
DATA TYPE EXPLANATION
const data members You cannot legally assign a value to a const variable after it is created. Any value must be supplied at the time of creation.
Reference data members References cannot exist without referring to something.
Object data members for which there is no default constructor C++ attempts to initialize member objects using a default constructor. If no default constructor exists, it cannot initialize the object.
Superclasses without default constructors [Covered in Chapter 8]
There is one important caveat with ctor-initializers: They initialize data members in the order that they appear in the class definition, not their order in the ctor-initializer. Take the following definition for the SpreadsheetCell class:
class SpreadsheetCell
{
public:
// Code omitted for brevity
protected:
// Code omitted for brevity
double mValue;
string mString;
};
Code snippet from SpreadsheetCellDefaultCtor\SpreadsheetCell.h
Suppose you write your SpreadsheetCell string constructor to use a ctor-initializer like this:
SpreadsheetCell::SpreadsheetCell(string initialValue) :
mString(initialValue), mValue(stringToDouble(mString)) // INCORRECT ORDER!
{
}
Code snippet from