In the last episode, we considered the fundamental aspects of object-oriented programming (OOP). In this episode, we will start to code all this in C++. We saw that OOP defines the concept of class which is the result of the process of abstraction and encapsulation as we saw in the example of the definition of the Rectangle class, which had the data members "largeur" and "hauteur" (TN: means "width" and "height") and had a "surface" method to calculate its area (TN: "surface" means "area"). A class, in the programming jargon, defines a new type that allows for the creation of variables of this type, for example three variables rect1, rect2, rect3, that are called in object-oriented jargon, "instances" or "objects". So how do you code this in C++ ? A class in C++ is declared with the keyword "class". For instance, to declare the class "Rectangle", we will write "class Rectangle" which defines the name of a new type then, we will include the data members and methods (also called "member functions") as we will specify later on. All this is closed with a semicolon. Do not forget this semicolon! This is a frequent error when writing the first few classes. This declaration defines a new type, called "Rectangle", that we can now make use of to declare variables, as we would do with any other type, with first the name of the type, followed by the name of the variable, As an illustration, to declare an instance, a variable "rect1" of the Rectangle class, we use the type Rectangle followed by the variable name rect1. For now, our program looks like this. We start by declaring the new type: class Rectangle for the time being, we don't have a class body; and we don't forget to end with a semicolon. Next in our main, we declare the variable "rect1" of type Rectangle. So how do we complete the class body? What data members and member functions do we need for this class ? Let's start with the data members,. The properties of a Rectangle are its width and its height. To declare these as data members, as for the fields of an usual data structure, simply declare the different data members with the type and the name of the variable For each variable we declare the variable's type and name followed by a semicolon. In the Rectangle class example, this leads to "double hauteur; double largeur" (TN: "hauteur" means "height" and "largeur", "width") it's as simple as that, as simple as for standard data structures! And it's the same for using the data members of an instance, with the same syntax as for a data structure. So we have the name of the instance followed by a period and the name of the data member that we want to use. For example, to use the height of the "rect1 Rectangle", we write "rect1.hauteur", which leads us to the following whole program. Here I have included the library "iostream" because I use input and output streams specifically displaying with cout and endl. Next, the usual "using namespace std;" Then comes the declaration of the Rectangle class that ends with -- don't forget-- a semicolon. Next, the two data members: height and width. Then here in the main, we declare an instance "rect1" of the Rectangle class and now we can initialize the height of rect1 at 3.0, and the width, also of rect1, at 4.0, and finally print the height of rect1 on the screen. All this is very much alike to the standard data structures presented in our previous course: Introduction to Programming. Note that the code given here does not compiled as is. You still require a litlle detail that will be explained in the next video. But apart from that detail, the rest is by large correct. Let's examine now the declaration of methods. Methods are simple functions that are embedded in a class. In the case of the Rectangle class, we will add the method "surface". (TN: "surface" means "area") A method is declared just like a function with the return type, the name of the method, then in parentheses, possibly a list of parameters; all this is the method header, followed by the actual definition of the method: the method body within braces. The only difference is that the methods are declared inside the class itself. In our example of the Rectangle class, the method "surface" is included here in the class with, its return type -- double because this method shall return a double --, its name, no need for parameters here, and returns the product of the height and the width. We could ask ourselves "Don't we need parameters?" Indeed, if we had written it as an ordinary function, --not a method but a function in the usual sense -- would we have had to pass the height and width as arguments to the function so that their values can be used in the computation. So why for this method in the Rectangle class don't we need to pass any parameter? The answer is that the height and width are data members of this class. Since "surface" is part of the Rectangle class, the method has access to the height and width of the class. Technically, this is called "class scope", that is, that all the data members of a class are accessible from anywhere in the class and in particular from each of its methods. For example, all the methods of the Rectangle class can access the height and length. Therefore it is unnecessary to pass these variables as arguments to the methods. In summary, a method is simply a function that is particular to a class, so is put in the class, thus has access to the data members of the class. This is very important: do not pass data members ar arguments to class methods. This is typically a beginner's mistake. In our example we have exactly this, we have a method "surface" that does not take any parameters but can access the rectangle's height and width that have been declared in the class. That being said, it's not because we don't pass the data members as arguments to these methods that the methods shall not have any parameter at all. Of course, if the method needs certain parameters from outside the class to operate, then parameters would need to be declared. For example, suppose that we have a class "FigureColoree" (TN: means "ColoredShape") and in this class, we would have several data members as well as a method "colorie" that colors the shape (TN: "colorie" means "to color"). This method should receive a color [from the outside] and would modify the color of the instance of the class FigureColoree. "Color" is another type that we would have defined as another class or with a "typedef". We could for example declare a shape, an instance of the class FigureColoree, and some red, an instance of the class Color, and, jumping ahead a little on the syntax, color the shape red. What I want to illustrate here is that the color "red" comes from outside the class FigureColoree and is not part of the class FigureColoree. That's why here we have to pass it as an argument. It is not a data member, so we have to pass it as parameter to the "colorie" method. We saw that methods are a particular form of functions that are declared in classes But doing so, frequently makes the code less easy to read. For example, we don't have a comprehensive synthetical view of all the prototypes of all the methods offered by a class. For this reason -- a better readability -- but also a better modularization, that is to say a better separation of the interface and the implementation, into two different units, for all these reasons, it might be necessary to define some methods outside of the class. This does not change anything of what I said earlier, but we are simply organizing the code a bit differently by defining the method outside the class while keeping its prototype inside the class. It changes only one single thing: if we define the method outside the class we have to tell the compiler that it is indeed a method of a certain class, and not a (usual) function. Thus the class to which the method belongs is indicated in the method definition in front of the method name: the class name followed by what is known as the "scope resolution operator" symbolized by a double colon ": :" For example, in our Rectangle class, we declared and defined the method "surface". If we want to define this method outside the class, what we keep in the class Rectangle is the prototype of the method surface. The method's definition, outside the class, will now have the name "surface" preceded by the class name and ": :". The definition is exactly the same as before, but with the method name preceded by the class name. Let's consider now another aspect of methods. There are actually two kinds of methods: methods that can modify valid instances as we saw earlier the "colorie" method of the "FigureColoree" class could modify and change the "color" of an instance. Such methods are called "non-const methods" or "non-const member functions". We distinguish these from methods that cannot modify their corresponding instances; for instance, the method "surface" of the Rectangle class: computing the area of a rectangle does not modify the rectangle itself. These methods are called "const methods" or "const member functions". For const methods, it is a good habit to signal these to the compiler and to other programmers that will read your code by adding the keyword "const" after the parameters list, at the end of the header, to say that they cannot modify instances. To illustrate, in the Rectangle class, we would define here the prototype of the "surface" method by adding, here at the end, the keyword "const" which will also be added on the definition of the "surface" method, here, at the end of its header. We can check, here, that the "surface" method does not at all modify neither the height nor the width. By using the height and width, the method does not modify the instance. If you label a method "const", that is to say, you mark the method as a const method, but contrarily, the method modifies the instance, which means that in fact it is a non-const method, then you will get an error message from the compiler saying "assignment of data-member" then the member that you modified then "in read-only structure". Here the "read-only" means it is considered that through this method you cannot modify the member cited, we can only "read", but not modify, "write", it. So in such a case, there are two solutions : either you effectively made an error and you have to remove the word const, or you really wanted the method to be a const method. In this case, you made an error in the definition of your method. So, now you know how declare and define methods of a class but how do you use there functionalities? To do this we will use a syntax already seen with vectors and strings and almost identical to the syntax for using data members: the name of the instance, followed by the name of the method and in parentheses potential arguments that would be passed to the method. In the case of vectors, you wrote "tableau.size()". Actually, it's because "vector<double>" is a class and "tableau" is an instance of this class (TN: "tableau" means "array") and in this class, we have a method "size". For instance, to call the "surface" method of the Rectangle class on an previously declared instance rect1 of the Rectangle class, we could write "rect1.surface()". The usual format is "name of the instance"."name of the method" and possibly some arguments. Here "surface" doesn't have any parameters, and so we only put the empty parentheses, just like when calling a function that does not have any arguments. So now, our program looks like this. We declare a class "Rectangle", -- don't forget the semicolon at the end -- In its body we declare two data members, representing height and width, both of type double, and finally a method that does not modify the object that it applies to, that is called "surface", that does not have any parameters that computes the area, and returns it as a double defined as the product of the data members: height*width Here in main we declare an instance rect1 of the Rectangle class We assign the height of this instance the value 3.0 : "rect1.height = 3.0;" and the width of the instance rect1 the value 4.0 and call the area method "surface". Here the "surface" method does not take any argument and applies to rect1, so it is the area of rect1. This will print "surface :" and the value 12 which is 3 times 4. Note again, as in the first example, strictly speaking, this code cannot compile as is, you still need a little detail that will be presented in the next episode. It's important to understand that when "rect1.surface()" is called, "surface" is applied to "rect1" and takes the height and width of "rect1". Each instance has its own set of values for its data member. If I had declared in the same way three rectangles, that I I would assign, for "rect1" a width 4.0 and a height 3.0, for "rect2" a width 11.5 and a height 3.8, and for "rect3" some large values. Each of these three instances is a different variable in the memory and has its own data members, so when we call "rect1.surface", it is the general method "surface" of the Rectangle class that will be applied to the object "rect1" and the definition of which, in its body, will have access to the individual height and width of "rect1" And if we call "rect2.surface()", we will get the area of "rect2" calculated with its own height and width. So in brief we can say that calling "rect1.surface()" is like calling the "surface" method of the Rectangle class with, as parameters, the address of "rect1" which contains the needed values to do the computation. So this concludes our first episode on how to write real OOP code in C++. We saw how to declare members : data members and methods (a.k.a "member functions"), essentially this axe here, and we will consider this other axe in our next episode.