In the previous episodes, we have learnt how to declare classes and class instances (i.e., objects). For example, if you wish to declare a "rect" instance of the "Rectangle" class, you will simply write it like this : "Rectangle rect;" Now, we could wonder how to give values to its data members. Here, we would like, for example, to initialize the data members "hauteur" and "largeur" (TN: means "height" and "width") of this "rect" instance of the "Rectangle" class. In order to give values, we could resort to the previously discussed setters such as "setHauteur" and "setLargeur". Thus we would individually give a value to each member. We are doing just that here, declaring a "rect" instance of the "Rectangle" class. Then, we are using a double-type auxiliary variable "lu". Through this variable, we will read, for example, the height, printing here a message for the user and retrieving the value inside "lu" through "cin". Then, with this setter "setHauteur", we will assign the height. Then, similarly, we will ask the width, read it in "lu", call the setter "setLargeur" and assign the width of our "rect" instance. However, this is a poor solution. Indeed, since we are to initialize all the data members, this solution presupposes that all data members are either part of the interface, thus being public -- which is not acceptable in regard to the encapsulation of the object-oriented conception -- or assiocated with a setter. This also shatters the encapsulation because it results in the interface being dependant on the internal representation of the data members since we would need one setter for each data member, However, the goal of encapsulation is to clearly separate interface and implementation. If we had, in the interface, a setter for each data member, the implementation choices would overflow on the interface, thus breaking the encapsulation. Also, regarding conception, this means that the task of initializing all data members will befall on the programmer-user of the class. Since they will have to initialize all the data members, we are taking the risk of an ommision -- a major conception flaw. Normally, the developer-programmer of the class should be the one initializing the data members or at least giving an initialization possibility regarding a few data members carefully chosen by the class developer. The programmer-user of the class should not have to think of all the possible data members having to be initialized. Another solution is, as usual, to create a specific method tasked with this initializing the data members. Here, we would thus create a specific method initializing the data members. For example, we could create such a method called "init" which would initialize both members "hauteur" and " largeur" of our "Rectangle". In order to function, this method will receive here, a value "h" which will be assigned to the height and a value "L" which will be assigned in the width. This method would be like a setter for both "hauteur" and "largeur" at the same time: a setter initializing all the data members needing to be intialized in one go. We would use it as follows. We would declare a rectangle "rect". Then, we would call the "init" method, passing two values. For example 3.0 for the height and 4.0 for the width. This way is certainly not a bad way to proceed. Actually, it is such a good way that is is already available as such in C++. Such methods are called the « constructors ». Constructors are particular methods tasked with initializing the class. A constructor is thus a method which is automatically called upon the declaration of an object; right when a new instance is created. Its purpose is indeed to realize what must be done at the start of an object's life. For example, initializing its members. In order to declare a constructor, we simply need to declare, like this, a method which name is none other than the name of the class. This method will receive, if necessary, parameters. Then, we will write its definition like of any other method. For example, in the case of our "Rectangle" class, we could declare the constructor here. "Rectangle" - the exact same name as the name of the class. Our constructor will receive two parameters in order to initialize the height and width. Constructors function almost like other methods. There are a few differences, though. Firstly, there is no return type; we did not write anything, not even "void", before the constructor's prototype. This means that there is no return type. Also, the constructor name is absolutely identical to the name of the class. Finally, constructors are called automatically whenever an instance of the class is declared. For example, if we write, simply, the declaration of a "rect" instance of our "Rectangle" class here, the so-called default constructor will be automatically called - we will go back to this later. A constructor is thus called whenever an instance is created: this call being explicit or not. These are the constructor specificities. However, just like other methods, constructors may be overloaded and even have default values for their parameters. We will expand on this later. For now, just be aware that there can be more than one constructor since they may be overloaded. We can have several constructors with the same name -the name of the class- but with different parameters. We are talking about the class constructorS. Now, let us go back to our initial example. For now, we only wish to declare one single constructor. How should we concretely proceed? We still have the declaration of the "Rectangle" class. The data members are still private. Obviously, the constructor will be public since it will be used by the user-programmers of the class; constructors need to be accessible. Therefore, the constructor is part of the interface. We would have here a constructor with the same name as the name of the class. Its purpose is to initialize the data members height and width through received parameters "h" (assigned to the height) and "L" (assigned to the width). In the public part here, we would have the prototype and the definition of the constructor. Then would follow all other methods we decided to implement in the interface. By the way, since we now have a constructor, we can freely pass the initial values during the construction of every instance of the "Rectangle" class. Therefore, it may not be necessary to keep these setters which let us modify each data member. This choice befalls on the programmer of the "Rectangle" class. Should we, yes or no, be able to modify the data members "hauteur" and "largeur" after the construction or is the initial value enoguh? Let us now see how the constructors are called. We said that they are automatically called upon the declaration of every instance. But how are the parameters passed? In order to pass the parameters, we simply need, during the declaration of a certain class instance, to put, between brackets, the different values we will pass as arguments to the parameters of the corresponding constructor. For example, in the "Rectangle" class, we have a constructor with two parameters. We will thus pass, during the declaration of the "r1" instance of the Rectangle class, between brackets, the two values for the parameters of the height and the width we have previously declared. The constructor's purpose is thus to initialize the data members. But what about the data members which are objects themselves? Let us take an example which will be improved later once we have discussed the inheritance notion. Here, we suppose that we have a "RectangleColore" class (TN: means "ColoredRectangle"). In its private part, this class contains a "Rectangle" data member which is itself an instance, an object of the "Rectangle" class. Another data member would be, for example, a color (TN: "couleur" in French). In order to make things easier, we could suppose that "Couleur" is an enumerated type or an integer. How do we initialize this "Rectangle" data member of the "RectangleColore" class? Since it is itself an object of a class we will have to call its constructor. To that end, we could imagine -- though it is a poor solution -- to write the constructor of "RectangleColore". -- we thus have the same name here as the class "RectangleColore" -- this constructor taking the parameters "hauteur" and "largeur" in order to initialize the rectangle and a color parameter in order to initialize the color data member. In the constructor's definition, we would copy an anonymously-created rectangle which will receive the parameter "h" and the parameter "l" in its own constructor. This rectangle will then be copied in the "rectangle" data member of the "RectangleColore" class. Then, we could initialize the "couleur" data member by copying the value of the color received here. This syntax, like here, "Rectangle" without any variable name in the middle of the constructor call is absolutely valid. This will create a so-called "anonymous instance" -- it is not named -- of the "Rectangle" class. This indeed creates an existing "Rectangle" with its height and width. This "Rectangle" will then be copied in the "rectangle" data member of the current instance of the "RectangleColore" class. Like this. This instance being created and initialized by the constructor. As we can see, we will have two "Rectangles". A first anonymous "Rectangle" here which is initialized through a call to its constructor. And a second "Rectangle", here, the "rectangle" data member of the instance we are currently initializing in the constructor of "RectangleColore". This is therefore a very poor solution. We thus need to find an alternative. It would be ideal for the classes possesing objects as data members to be able to directly call the constructor of their data members. Here, for exemple, we would like "RectangleColore" to directly call the constructor of the "Rectangle" class during the initialization of its "rectangle" data member without needing to resort to an intermediate copy. It is much better to put things at the right place than to pass by a copy -- especially if the object is voluminous. To that end, C++ offers us a so-called "initialization list" in the constructors. The purpose of this initialization list is indeed to call the constructors of the object data members, but also to initialize the data members which are not objects. These non-object data members are called "basic types" (TN: or "native types"), such as "int" or "double". It is very good practice to use an initialization list in order to initialize the data members instead of doing so in the constructor's body. The general writing of an initialization list is done as follows : Between the constructor header - which includes the same name as the name of the class and an eventual list of parameters here - and the constructor's definition, we will write the initialization list. This list starts with a colon. Then, for each data member, we will have here the name of the data member followed by a syntax similar to the one used for an instance declaration. Namely, the call of the constructor corresponding to each data member here between brackets, followed by a comma if there are several data members. We will keep going like this for every data member for which we need to call its constructor, using this parentheses syntax. Let us go back to our "RectangleColore" example. Be reminded that "RectangleColore" has for member a "rectangle" data member which is an object of the "Rectangle" class. Also, remember that the "Rectangle" class had a two-parameters constructor tasked with initializing the height and the width. Also, our "RectangleColore" class, in addition to the rectangle data member has a "couleur" data member. The "RectangleColore" constructor -- which we are interested in -- will receive parameters in order to initialize its "rectangle" data member and other parameters in order to initialize its color data member. This initialization will occur in the so-called initialization list here, starting with a colon. To that end, we will call the constructor of the "Rectangle" class, taking two parameters here for the "rectangle" data member. Here will we put the name of the data member, "rectangle", the same name since we are precisely initializing this very data member. We will write here the name of the "rectangle" data member using the same syntax as if we had declared an instance, initialized a variable here. Here is thus the call to the corresponding constructor of the "Rectangle" class. Then, the comma separating the different parts of the initialization list. Now, similarly, we can initialize the data members even if they are of the type double or int. Here, the non-object data members will follow a similar syntax. Here, between parentheses the value we wish to pass to the data member, still conserving the name of the data members. For example, if we wish to declare an "r" instance of "RectangleColore", calling here its only constructor taking three parameters. For example, with a height of 3.5, a width of 4.5 and color which would, for example, be defined as "rouge" (TN: means "red"). Here, we indeed have the declaration of an instance with a call to its constructor. What will concretely happen? Why, this will effecively create, in the memory, an "r" instance of "RectangleColore". This instance contains a "Rectangle"-type data member which has itself a height and a width. It also contains a "Couleur"-type data member. Upon the call to the constructor, we will plug in here and execute the colon section, thus calling the constructor of the rectangle data member -an instance of the "Rectangle" class. To the constructor, we will pass the the parameter "h", containing 3.5 to the "Rectangle" constructor in order to initialize the height value of the rectangle data member of the "r" instance of the "RectangleColore" class. Similarly, here, this 4.5, that is, the "L" parameter of this constructor will be passed to the constructor during the execution of the initialization list. It is the second parameter of the constructor of the rectangle data member instance of the "Rectangle" class. Here, we will initialize it to the value 4.5 Here, the "Couleur"-type last parameter "rouge" will go here, in this section of the initialization list, thus initializing the color data member directly. Using this section beginning with a colon -- called the "initialization list" -- is very recommanded. First of all, it prevents, as we have seen before, to resort to copies of all object data members (class instances). Also, it lets us regroup in a very compact and readable way the initialization of all the data members. Finally, it grants the initial values to all data members from the start, before the object has even been created. Of course, these initializations can then be reused or even modified within the constructor's body; this is extremly rare, though. We are illustrating it on this slide only because it is something possible, although you will very rarely have to use it. For example, here is the constructor of the "Rectangle" class where we receive both parameters to initialize the height and the width. In the initialization list, we have initialized the height. Though, it would be better to initialize the width aswell, after a comma. We have not done so in this example in order to show you that the width is precisely not initialized in this portion of the constructor. Starting from there, the value is undefined. Then, as soon we assign a value to the width, of course, the width will have the assigned value. What you need to understand is that we have a section of the constructor where the width is not initialized. This is one of the reasons why we recommand to use the initializer list (TN: here called in French "colon section"). This section is executed from the get-go before we even enter the constructor's body. It is executed from the very beginning Thus, before we even enter the constructor's body, we have initialized the height to the value "h". If we follow these advice, our program will look like this. In the declaration of the "Rectangle" class, in its interface, we offer here a constructor taking two parameters "h" and "L" initializing the height and width directly in the initialization list starting with a colon with the values of "h" for the height and "L" for the width. The constructor's body is thus empty. This is very frequent in C++ constructors because we already have this initialization list which it is recommanded to use. By the way, please note that we have here a data member name and here a parameter name. Indeed we are passing a parameter to a data member. Similarly, we have here the "largeur" data member and the parameter "L" Therefore, there is no masking problem nor name ambiguity. Thus, we could naturally name our parameters "hauteur" and "largeur" and write something like this "hauteur(hauteur), largeur(largeur)". There is no ambiguity here. This "hauteur" word refers to the height data member while this "hauteur" word here is a parameter, a value received from outisde. Similarly, this "largeur" word here refers to the width data member and this "largeur" word here obviously refers to the width parameter. We can encounter this syntax in several constructors in programs written like this, giving the same name to parameters and the data members they will initialize in the initialization list. There is no ambiguity, no masking. This concludes our introductory episode regarding constructors in general. We still have a few point to discuss, such as the "default constructor" -- there can only be one default constuctor; thus the singular form. We will also discuss the "copy constructor". And, in a last episode, we will discuss what happens when we are done using an object, what happens at the end of an object's life.