 We will continue with types, straps, classes and objects and at some point we will make a transition into also understanding memory management, how to allocate space on the heap and how to manipulate it, how to return it back to the system and these two will go hand in hand for a while. So, last time we already looked at type def as a language feature, this is a way to just assign a new name to a type that you could already express with constructs in the language or libraries. So, in an extreme case you could take a primitive type like int or double and just give it a new name to make your code more understandable and readable. So, you could say that the ticket number of a customer is just an int or the time in an event simulation is just a double or you could define a compound type or a derived type such as pair string int and give it a shorthand name to reuse over and over in the code without typing that much. So, that is types and this will now become types available to you in the rest of your program. Now, the next thing we looked at last time was how to define structs. So, the reason why you would like to define a struct is that there is a logical record with multiple fields. For example, for every student we have a dole number which is supposed to be a unique key in the institution and then the name may be divided into first name and last name, date of birth and many other fields, grades and so on courses taken. Similarly, for the event simulation problem every customer might have a ticket number and arrival service begin and departure times. So, instead of using separate collection objects like queues and vectors or matrices etcetera with each field in a parallel way it is much better logically speaking to use one collection of records instead. So, instead of having a set or a vector of role numbers and a vector of names and a vector of date of births it is much easier to read the code if you say it is a vector of students or student records. And those records will now have these fields and then they can be accessed all through one handle variable. So, we looked at this simple starting examples you could have you could define a struct called a point which has an x coordinate and a y coordinate these are called members. So, double is the member type or field type and x and y are the member or field names. So, those are variables inside the struct. Similarly, you can define struct circle which in turn uses the definition of point just before and then circle also has a radius. So, and we also saw how you can initialize these variables with these types. So, if you want to define a variable called pt it is one of many possible points. So, point is the name of the type pt is a variable that has type point. So, pt is initialized with a list enclosed in curly brackets in this particular case the first element is 0.5 the second element is 0.9 those will be assigned in order to the declared variables inside the struct. So, 0.5 will go to x and 0.9 will be assigned to y. Now, similarly for circle one particular circle called circ is initialized to two things the first is a nested curly bracketed argument list for its point part the center part and the other is the radius part which is 2.3 in this case. Now, how do you access members after initialization? So, you can say circ dot radius or you can say circ dot center dot x. So, it is a hierarchical tree like structure and traversing down one level is done with a dot. So, circ dot radius, circ dot center, circ dot center dot x, circ dot center dot y those are all the paths accessing the atomic values inside this compound object called a struct. And passing them around passing these structs around in functions into and out of functions has exactly the same semantics and mechanism as individual atomic variables like ints and bools and doubles and floats namely the default is passed by value. But if you do not want that you can also pass this by reference. So, that is what a struct looks like and you also looked at these three styles of initialization the one is the silly way which is doing all the fields individually one by one well it is not that silly sometimes you may need it because you want to update maybe there is a counter value in the struct which you want to gradually update or you can do it as an expression without giving the name of the typed object. So, instead of calling it a circ you just say circle 0.6, 0.8 and 2 and that creates a circle variable with that given type with those fields, but there is no name. Now, you can stick it into a vector or list or whatever you like or you can declare that circ is a variable of type circle as we have seen in the previous slide. So, there are these three styles of initializing an object. So, then we started looking at constructors. Now, there are multiple reasons for this one is that maybe in the previous case 0.6, 0.8 and 2 were basic values which were directly assigned to fields or members sometimes you have to do a little bit of calculation to do it. For example, if we also redundantly created something called an area and we kept it in a circle naturally we would not like every constructor site of a circle to calculate its area that calculation should happen inside circle itself. And for that we wanted to create these things called constructors. Constructors are just function like objects which create the object itself. So, the constructor for circle will be named circle as well alright. Now, then we started talking about what happens when radius changes you would have to also update the area, but that involves something different in object oriented programming which is access control. Namely you will prevent direct assignment of radius. You will only allow updates to radius through some methods which will otherwise hide these variables radius and area from the clients. We shall see that when we come to access control. Now what is a class? So a class is basically a struct plus a few other facilities. First of all a class gives you more general constructors how to set up the initial configuration perhaps allocate memory which we will soon see. Suppose building up the object requires some extra memory allocation like in vector or in string we will see how the constructors do that. And similarly the destructors, destructors release resources and clean up the state of the object. So for example if you open a file then one of the resources that is allocated from the operating system is a file pointer that actually tells the operating system that there is an open file and characters written to the file should go down into the disk. When you destroy the file object or fstream object it is up to you or the implementer of fstream to release that file pointer back to the operating system. So the operating system can close the file. So you have to release memory resources as well as possibly external resources like disk files. And then there are methods which change the state of the struct members in clean and controlled ways. For example when you write to a file you have to use a writing method the less than less than and greater than greater than actually methods in the fstream or ostream istream objects. And apart from actually sending the bytes over to the disk these classes have to keep track of how many bytes you have written whether you have closed the file or not is there an over full disk is the file empty have you read to the end of it already. So those states are kept inside the object itself. Two more things so access control as a user of iostream or fstream you should be given access to methods for reading and writing that stream. But you should not be given direct access into the operating systems file pointer or how many bytes you have written those variables you should not see because you cannot you know mangle them from outside and confuse the system. So there are facilities inside C++ to reveal certain methods and members and to hide certain other methods and members using these three keywords public protected and private which we will look into next week. And finally there is this matter of extending classes. So suppose I have a point class and now I would like to have points with colors. So I can plot them on screen. So I want that to be red points and blue points and green points if they implemented of point already implemented a bunch of useful routines I do not want to lose those. I want to build on top of point so can I create a class called colored points which uses point as what is called a base class. So there is subclass, superclass, base class, extended class, roughly used equivalently. So that is called inheritance because some classes can inherit members and methods from their parent classes. So these are the four or five main things that classes provide. Now let us get into how say the points can define constructors and destructors. However earlier the point class only defined initializers. In fact we did not use class, we used struct. Now the distinction as far as today's lecture is concerned between classes and structs is also that in structs everything is public. Everyone can access everything in a struct whereas in a class you can hide and show selectively. So in this example because I want to show everything to the outside world without declaring public all over the place I have just said struct. So what does a struct point have? It has two members called x and y, they are both doubles and how do I initialize a point? I give it two arguments point double x double y and then as we saw last time inside you can initialize x to underscore x and y to underscore y. Now there are ways to disambiguate things but if your arguments were also x and y then naturally inside the function body you would get a little confused about which x you mean. So typically it is conventional to label the incoming variables with an underscore okay that tells you the correspondence easily and then usually what happens is the member x is assigned to underscore x and so on and so forth. That is a conventional way of writing constructors and then just to record the fact that the constructor has been called on the object will print out a message saying point. We can also print out x and y if we want and we will do that in the code. Now the next method so point and tilde point they are actually the constructors and destructor methods. The point method does not really have a return value because all it does is create and initialize this object. So there is no return type required and there is no point, there is no reason for giving it a new name so it is also called point which is the name of the class itself. Similarly tilde point is called the destructor. It destroys the state of the object and you can opt to release any other resources you are holding like a lock on a file or some control over a rectangular patch of the screen whatever you want to do there you have to release the resources. So here there is no resource to release we just have two variables and all we do is print out a message saying tilde point was called. So that is the easiest example of point construction and destruction. So let us look at actual code to see how it works out. Now in this particular code as you can see I have added a few more things for example apart from printing point with x and y and I am printing them in bracketed and separated by commas that is all. I could also do the follow so there is this special let us first comment this out and run the rest and then we will come back to what that commented statement is doing. So what does it do? It has two members initializer and a destructor and then a inside main I say point p t 3 4 that is all. So what does it say? So it just prints that point was created with 3 4 and then tilde point was created. Now what is this? So this is a special variable which represents the address of the current object typically the starting address from which this object is laid out in RAM. And this special symbol called this is available inside constructors, destructors and methods. So for example instead of printing out only the value of x and y I could also print out the address of this object just like we had addresses of integers and base address of an array there is a base address of an object. The advantage is that even if two different points have exactly the same coordinates we can distinguish between them by their address ok. So now and in particular this is a pointer to the current object and so you can write this arrow x and this arrow y in place of x and y ok. So you of course never do that unless there are other variables x and y confusing you because just x and y are shorter but if you wanted to say this objects x and this objects y then you could do that ok. So now coming back to that code let us now comment this statement in and instead drop that. So what happens is the members are initialized to the given values and then you print out that a point is being created at this address with x and y coordinates as specified and when the point is destroyed you say that this the point at this address has been destroyed and as you already saw if I run this now it says a point has been created at this address which is printed in hexadecimal and it has x value 3 and y value 4 at the moment. You can of course change that and when the point is destroyed it just prints out the address note that the addresses are the same ok. Now so of course an interesting thing to do is to say this is point 1 and now you say point 2 now what happens 2 points are being created 2 points are being destroyed. So now if I run this you see that 2 points are being created and 2 points are being destroyed. Let us increase the number of points 3 points now do you notice a pattern here ok things have been destroyed in exactly the opposite order to which they were constructed. If I run this again the absolute addresses have changed in a different run but the deallocation still happens in reverse order of allocation ok and the reason is partly that all this storage is being allocated on the stack. So first in first out now the next thing that we stumbled upon little last time is how to initialize constant fields you might in your application want points to be immutable namely once they are created with an x and y coordinate they should not change. You might have an application like that to play it safe and prevent anyone from accidentally changing an x or a y you could declare them as constant that we have already seen ok. Now why might you want x and y to be immutable after the object is created for example you might be using x or y as the key in a map or a multi map. If you let people change their x and y's then you will be obligated to remove it from the map and then insert something else in. If you do not want that you want to say that well as soon as the point is created its keys are set forever and only those things can go into a map. So that is one reason why you may want a constant. The points are being destroyed after they were created so what is the use of that? Oh no so you know of course in a real application do a bunch of stuff between them. So for example you could say something like that or you could say you could do all that kind of thing. Generally speaking you would do a bunch of calculation and only then the end of scope would kill everything ok. Now we could try some other games for example let me start a curly brace and now we say maybe one of those is created inside the curly brace and then you again do some computation inside the curly and then close the curly. So this time what happens? In this case very similar things happen. This is inside the curly and that is why this goes out of scope first. Now yeah. In general it is not the way you were destroyed when its scope is over. Yes. Then the memory is not freed in the general case. What do you mean? Like if I had defined just an int instead of the point over there. Int a. Yeah when main gets over its scope is over so the memory allocated to a isn't it freed? Yes it is. But when we are doing structs we need to separately free it. No not so. Then what was the point of doing the tilde point over? So we will start seeing why you need the tilde destructors when we start doing our own memory allocation. So if you only have things like ints and doubles then tilde essentially does nothing but doesn't have to do anything. So the storage for point will be freed in exactly the same way as the storage for a will be freed and you don't need to do anything about it. So are the questions clear? So because our points only have primitive variables in it there is nothing to release to the system. So similarly here a will be destroyed at the point this curly closes. Similarly pt3 will be destroyed at the point this curly closes. Of course within there is no facility to print out anything. For point we can intercept the act of destruction and print out when it is being destroyed that's all. So coming back to constant field if you declare x and y as constant doubles and now you want to initialize them from a given double x and double y like so. The important thing is that even before you open the body of the method or the constructor you initialize with a column. So after the parameter list of the constructor is finished you give a column then for every field you want to initialize you have to say x initialized from underscore x, y initialized from underscore y and so on. This is just a language restriction that cons need to be initialized before the method body begins. This restriction doesn't exist in Java for example. But in C++ that's how they have designed the language. So if you want to initialize cons they have to go before the body of the method. Once x and y are written with values like this no other method or any outsider can ever change x and y inside point that will not be allowed. So as a demo so here's cons point in which x and y are cons doubles and the initialized as I said in the slide and then I print out that similarly point this as x and y. Now so I'll compile this don't look at the all the other methods right now but suppose I say something like x equals x plus 1 that will not be allowed. Assignment of we don't need to remember point x that will not be allowed not only here but anywhere. You cannot even inside main do something like pt1.y++ that will not be allowed either. Increment of we don't need to remember point y. So no one can modify those values once initialized they are there fine. So let's see now the next thing we'll look at is what's called the copy constructor. So what happens if you say point pt2 equal to point 1. Now earlier when you are talking about structs without defining any such constructors what I said is that the all the fields in one structure copied over to the other struct. But again you can intercept that you can intercept that and do something different. So how is it for example if you wanted to write a copy constructor for points you would set it up as follows you would say that here's another constructor which doesn't have a return type it's name is point and inside I'm going to pass a constant reference to another point and I have to build this point by copying the values of the other point. But you don't necessarily need to you can do something else. So in this case x will be initialized to other dot x and y will be initialized to other dot y. And inside the body generally don't do anything here because we want to trace we will print that a point has been created at this and it's been copied from other. But other is a reference to an object so we have to take an address to see what its memory address is huh all this has to be done yes these are all methods with going to the same structure class. So this is called a copy constructor it builds the current this object out of a reference to another object which you are not allowed to change you're only allowed to read other than do something with it. Now in this case it's very trivial I'm just copying the values of x and y but you may think of other ways of doing business. So let's look at how the cop constructor works in practice. So here is a copy constructor const point other and x is copied from the other guy and y is copied from the other guy and what does main do it first creates point one with three four and then it creates point pt2 equal to pt1. So internally what will happen is whenever an equal sign happens as an assignment the c++ compiler will replace the equal by a call to your copy construction method. So if I compile this on that so see what happened first is that make point is not working pt1 is created at this address 2130 okay with values three four and then a new object is created at 2120 and its values are copied from 2130 the first object and then as in stack order the second object was destroyed first and the first object was destroyed later. So that's how you write a copy constructor. So these three things are all important a constructor a copy constructor and a destructor to avoid yeah this function will be called anytime you assign one point to another point. So equal to has now become a shorthand for copy construct now apart from constructing and destroying things let's look at a first method and this will be for mutable points not constant points. So suppose I want to move the point through dx and dy then the body of the method will just say x plus equal to dx y plus equal to dy that will change the position of the current point. So this is a mutable point or you could say something like void print without any arguments that's the current point and you could say something nice like what we are doing in the constructor itself print x and y or you could even say read this from a file. So let's let's code up read and write to be sort of consistent and this also brings up a messy aspect of seen and see out that some students pointed out. So let's say print and I'll say something like x quote and y but if you say load so you would write it like c in x y. Now the important thing is that when you read numbers the runtime system implementation of I stream and O stream of I stream depends on an illegal character or space or punctuation to decide when your number finishes. So if it says enter an integer x into the terminal if you type one five return that return instructs I stream that the number is finished. So unless you give some delimiters like this space or the new line seen will not work correctly. So you cannot just write you know the two are not symmetric you would think that ideally if seen can if see out can write out x and y like this seen should be like that it's not symmetric like that you have to provide the delimiters. So that seen can work properly you have to either give a new line or at least you have to give some space. So here is a simple point method which can move which can write itself to see out which can read itself from see it. So what have we seen so far we have looked at type defs a comfort feature then we have looked at structs everything is public and you can name fields with different types you can initialize them using curly lists. But the initializers can cannot do any calculations inside them sometimes you need that. And then we looked at how to replace standard initializers with constructors. An example of why you don't want simple struct initializers in all cases suppose I want to create a vector with a given number of elements n all having the value v. So then you can no longer use a struct to do that because a variable number of arguments is messy to pass it can be done but it's messy. So instead you create a constructor where the first argument is the number of elements and the second argument is the value of all those elements. And now it's trivial inside the body of point or vector to fill in the array with one fixed value. So that's why constructors are nice to have constructors will also usually allocate resources from the system it may open a file or it may allocate some memory more frequently. And therefore you have to align it with a corresponding destructor which will free up those resources. And finally I need a copy constructor so that equal assignment statements work correctly in the system. Assignment amounts to creating a new value and initializing it and that's why you need another method called a copy constructor which can also fill up the fields inside one struct given the values of fields in another struct of the same type this has to be a point that has to be a point.