I saw two different ways to use member initializer lists. The first one is like that:
class ClassName {
public:
arg_type_1 varName1;
arg_type_2 varName2;
// Constructor.
ClassName(arg_type_1 arg_name_1, arg_type_2 arg_name_2)
: varName1(arg_name_1), varName2(arg_name_2)
{
}
}
What is happening there is clear. In the constructor we have a list of arguments and we use them to initialize members of the class. For example arg_name_1
is used to initialize value for the varName1
variable of the class.
Another way to use the member initializer appears in the case of inheritance:
class ChildClass : public ParentClass
{
ChildClass(string name) : ParentClass( name )
{
// What can we put here and why we might need it.
}
};
What happens here is also clear. When we call the constructor of the ChildClass
with one string argument, it calls the constructor of the ParentClass
with the same string argument.
What is not clear to me, is how compiler distinguish these two cases (the syntax is the same). For example, in the second example, compiler might think that it needs to take value of the name
variable and assign it to the ParentClass
variable of the ChildClass
and then it sees that such a variable is not declared in the ChildClass
.
The second unclear point to me is why we might want to put some content in the body of the constructor from the second example. Even of there is nothing it already creates and returns an object using the constructor of the parent class.
Seeing an initializer in the list, the compiler first looks for member variables with that name. If it finds one, it tries to initialize that member with the given arguments. If it does not, it looks for a direct base class or virtual base class with that name, to initialize the base class subobject with the given arguments. These are the usual name lookup rules applied when you name something inside a class' method (including constructors).
In the rare and badly designed case when you have both a member variable and a direct base class with the same name, you will have to qualify the base class type, i.e. add the namespace:
It does not really return any object, it just creates that object. However, someone might want to call additional functions like this:
There could be many reasons why someone might want to do this. In General, since the child class is "more" than the parent class, it is only natural if it wants to do more in its constructor than just initialize the base class subobject.
Some words on object lifetimes: Before entering the constructor body, you have only constructed the subobjects of the new object. The object itself begins its lifetime when execution leaves the constructor body. An analogy could be a car and its parts: Before enterign the car's constructor body, you have inflated the tyres, assembled the enginge and stamped out the parts of the body. But your car isnt a car if it has not been assembled, wich happens in the constructor body. This is mirrored in the destructor and can especially be seen in the presence of exceptions: If an exception occurs during an object's constructor, its destructor will not be called. Only the destructors of the subobjects will be called that have already been constructed completely. This is because if the constructor has not completed execution, the object never existed and there is nothing to call the destructor on.