 So, what we are going to do is we are going to quickly look at the next lecture, but I want to sort of discuss this lecture because now that you know about member functions, all that I am trying to say here is that there are two special member functions that are associated with every class or struct. These are called the constructor member function and the destructor member function. So, what is a constructor member function? Every time so think about that V3 class that we just talked about. So, every time you allocate an object of that V3 class, a constructor member function is immediately invoked. So, the moment an object of a class is allocated, the first thing that happens is the constructor member function gets invoked and then you have access to it and you want to do whatever you want to do with it. So, because this constructor member function gets invoked immediately after allocation of the object, therefore it is a very convenient way to initialize the various data members inside the allocated object because this is going to get called immediately after allocation before you can do anything else. And if you just remember that that you know constructor member functions, a special member functions which are invoked on the parent object immediately after the parent object is created, the rest of it is just like any other member function. For example, you know this is the class V3 and here I am trying to write a constructor member function of the class V3. The funny thing about this is that the name of this constructor member function is the same as the name of the class. So, this is what C++ requires that all constructor functions of a class must have the same name as the class and they do not have any return type. So, these are the two sort of quirky things there that the name of the member function is the same as the name of the class if it is a constructor member function and it does not have any return type. It can take parameters just like any other member function, it can do whatever any other member function does. So, typically we do initialization, so for example here I am reading in three values and I am setting the x, y and z values to those. Here is another constructor member function which is just setting the x, y and z values to 0.0 and note that both these constructor functions both have the same name, both do not have any return type and both of them are residing within the same class definition. And C++ actually allows you to do this. You can have multiple constructor functions within the same class. The only thing that you have to ensure is that this list of parameters must have different types for each of the different constructor member functions. What it means is that here the three parameters are double, double, double. I cannot declare another constructor function whose three parameters are also double, double. I can declare another constructor function which does not take any parameter like I have done here. I can declare another constructor function which takes just one double parameter or four double parameters or two double parameters but I cannot declare another constructor function which takes 3 double parameters. So, you can define as many constructor functions as you want, but they must differ on the types of the parameters, the type list of parameters. And now if there are multiple constructor functions, will there be a confusion about which one to invoke immediately after allocating an object? So, that is not the case because if you are allocating an object like this, let us say myobj1 of type b3, then I have not provided any parameters over here for the constructor function. So, this constructor function will get invoked, constructor function that does not require any parameters. But if I say you know myobj2 is new v3 something here. So, I am saying allocate a new object of type v3 and pass these as parameters to that constructor function. So, now this constructor function will get invoked because this is the only constructor function of v3 that can accept 3 double valued parameters. So, here is another example which sort of shows this more clearly. So, here is the same class v3, there are these 2 constructor functions, same name, but type list of parameters are different. This takes 3 double arguments, this takes no argument and here is the main function. So, in the main function I have declared an object a of type v3 and I have specified some parameters for the constructor function. So, it is obvious which one is going to get invoked, this one is going to get invoked because this does not accept parameters, this accept 3 double parameters and here I have provided 3 double parameters for the constructor function. So, note also the public declaration here, the constructor functions have been declared public because they are going to be invoked from the main function after the objects have been allocated. So, for any member function to be invoked from the main function, it has to be public. The moment you declare a function as private, it can be accessed only within that structure, member functions, it cannot be accessed from outside. So, in this case I am allocating object b of type v3, but no parameters have been passed. So, this constructor function is going to get invoked. Here I am dynamically allocating an object of type v3 passing these 3 as parameters, so that constructor function gets invoked. So, it does not matter whether you are doing dynamic allocation or static allocation, does not matter whether it is in the stack or it is in the heap. Whenever an object of a particular class is created, the first thing that happens is the constructor function gets invoked, which constructor function depends on what parameters you are passing when you are creating an object of that class. These are the parameters to the constructor function. So, if you are passing 3 double parameters, this will get invoked, if you are passing that. So, here I am just saying allocate an object of type v3, no parameters passed, so that constructor will get invoked. So, these are special member functions, they are just like any other member functions except that they are called immediately after the object gets created. And you cannot call them later on, you cannot call them explicitly later on in most circumstances, there are certain circumstances where we can call them, we will study that in the next class. But the way to think of these is that these are going to get invoked immediately after the object is created. And therefore, you can do all kinds of initialization with it after the object is created. And just like constructor functions, there are things called destructor functions. So, whenever an object of a particular class is being deallocated, memory for that is being freed up, the destructor function will be called immediately before freeing it up. So, constructor is called immediately after the object is allocated, a destructor is called immediately before the object is freed up. So, it is a convenient way to do some bookkeeping, cleaning up and similar tasks. And the thing to remember is that C++ mandates that a destructor function's name must be the same as the name of the class with a tilde before it. So, constructor function is the same as the name of the class, destructor function is tilde name of the class. And a destructor function does not take any parameters. And then within that you can do whatever you want, you can access other member functions, you can access data members, whatever. Remember the destructor is being called just before the object is deallocated. So, when the destructor is called, you still have access to everything in the object. After the destructor call after the destructor function returns, then the object is going to get deallocated. So, within the destructor function, you can access everything within the object. But that is sort of the last time you see that object. After that, that object will be gone. So, and of course, you know, because you cannot put different kinds of parameters here. So, therefore, you cannot have multiple destructor functions because then there would be confusion about which destructor function you are trying to invoke. They do not accept parameters, they all have the same name. So, here is a simple example. So, this class V3 has some constructors, has some destructors. So, here I am allocating an object A of type V3 on the stack. This is a local variable. And I am passing these parameters to the constructor. So, the constructor function for V3 will get invoked here and it will initialize the data members x, y, z of A to these values. Now, within this pair of braces here, I have defined another object V of type V3. So, once again the moment this object gets created, again the constructor function is invoked. But of course, this time there are no parameters to pass to the constructor. So, the constructor which does not require any parameters will be invoked. Then I am doing some operations here on A and B and then I am closing this brace. So, when I close this brace, basically this object is no longer accessible outside this. So, this brace is saying that this is the scope of this definition. This definition, this object can be used only within this. So, when I encountered the second brace, this object B has to go because it ceases to exist after that enclosing pair of braces is over. So, since it ceases to exist, therefore it must be deallocated and therefore the destructor for B will be called when you come here. And then here there is a new V3 something. So, here again the constructor for V3 will be called because you are allocating a new object of type V3. Immediately after allocation the constructor will be called with these as parameters. Then you are doing some operation, then you are deleting, basically you are deallocating this object that you dynamically allocated here. So, once again you are deallocating an object of type V3. So, the destructor will be called before the deallocation. And finally, when you say return 0 and go back, then the activation record of the main function is going up, is being popped off the stack. So, all the local variables that were declared in main function are being deallocated now. So, A will be deallocated and again the destructor will be called. So, over here you have one constructor of V3 called here, another constructor of V3 called here, a destructor of V3 called here because this object is being freed up over here, a constructor called here, a destructor called here and finally a destructor called when main returns because this local variable has to be deallocated from the stack and every time an object of type V3 is deallocated just before the allocation destructor has to be called. Is that clear? So, all that you need to remember is that creation of an object is immediately followed by invocation of the constructor which constructed depends on what parameters you have sent and deallocation of an object is immediately preceded by a call to the destructor. So, are there any doubts? So, of course, the destructor also has to be public because it will get called from the main function when the objects are being allocated and deallocated. So, are there any doubts about that? For your purposes, the only difference between a struct and a class is that everything in a struct is public by default, everything in a class is private by default. You do have constructor functions for structs, you have destructor functions for structs, fine? Okay. So, now let us go to the quiz then. So, this is the first question. A private member function of a structure can be invoked from another member function of the same structure, a member function of another structure, an ordinary function which is a non-member function. Now, I can write functions in my program and I can write functions inside structures and classes. So, functions that are right in my program outside structures are non-member functions and the main function in the program, okay? Next one. So, consider the class definition, class CL, there is a data member which is private and there is a member function which is also private, then B is another data member which is public and F2 is a member function which is public. So, which of the following is or are true of the class CL? A and B both can be used in the body of B2, B but not A can be used in the body of B2, A cannot be used in the body of F2, B cannot be used in the body of F2. So, these are member functions defined within a class and the question is which data members can you access? Next one is, this should be easy. By default, everything in a struct is assumed to be what and everything in a class is assumed to be what. So, of course, if you have been awake, then you should be able to answer this very easily. So, accessor and mutator functions can be used to do which of the following. Read and write only private data members, read and write any data member, higher internal representation details of data members and expose internal representation details. Last one. So, class CL has three constructor functions, which of the following must be true. So, for some reason this color has come out to be different here, it does not mean that this is the right or the wrong answer. So, the constructor functions must have different names, the constructor functions must have different return types, the constructor functions must have different lists of parameter types and all of the above. Multiple constructors in the same class. Let us quickly look at the answers to these questions. So, a private member function of a structure, a private member function can be invoked from another member function of the same structure. So, private members are accessible within the structure freely, but they are not accessible outside that structure. So, private member function can be invoked from another member function of the same structure. It cannot be invoked from a member function of another structure, cannot be invoked by an ordinary function, cannot be invoked by the main function. Private things can only be invoked within member functions of the same structure. So, here A and B are data members. So, all member functions can make use of A and B because member functions have access to all the data members within the structure right. So, A and B can be used in the body of F2 the others are not correct. So, it does not matter whether the members are public or private within the body of the structure within the member functions of the structure you can make use of all the data members. Private and public only refer to accessing from outside the structure. So, this is simple you know everything instruct is public by default and in a class is private by default. So, access it in mutator functions can be used to read and write any data members not just private data members and they are really used to hide the internal representation details not to expose and if you have three constructor functions then all of them must have the same name the name of the class none of them have any return type, but they must have different lists of parameter types. That is what we just saw ok. So, now let us look at the practice question. So, in the last class we studied about directed graphs right. We basically used this struct my node as the representation of a node and we said that all the nodes in the graph are going to be in an array named nodes and the idea of a node is the index in the array. This is exactly the same as what we did in last class right and this was the struct my node that we used in last class. These are the two things that I had asked you to you know work it out yourselves and one possible way of doing this I mean some of you had made these arrays full blown arrays which is a bit wasteful of memory. So, one possible way of doing this is to define linked nodes like this right. So, you keep a node ID and then you have a next pointer which points to linked nodes again and then you can have an entire chain or entire list or entire queue whatever you want to call it of outgoing node identities of nodes to which we have outgoing edges and similarly you can have an entire chain of identities of nodes from which you have incoming edges. This is part of last class's question right. This is like the linked taxi. So, you can form a chain or queue of node IDs and outgoing will have the list of all node IDs to which there are outgoing edges and incoming will have the list of all node IDs from which there are incoming edges. So, now what we want to do in today's class is that we want each node and each edge to also have a weight and let us say that this weight is a float type. So, for example, if you think of you know these nodes as cities and these links as roads or some kind of maybe train lines between them. So, then this might represent the distance in kilometers and these numbers might represent maybe the population of the city or something in you know lax or something right. So, there are numbers that we want to associate with each node. It denotes some property of the node. It could be the total population of the city, the total amount of revenue collected by taxes whatever and you also want to associate numbers with the edges which could represent you know maybe the distance between the cities or you know the average time it takes to go from one city to another whatever there could be different kind of things one can interpret. So, what we want you to do is we want you to modify this my node and linked nodes definitions as is shown here to be able. So, in fact, instead of calling them structs I would encourage you to use classes and as I said for all practical purpose in this course struct and class are going to be the same except that in a struct everything is public by default in a class everything is private by default right. So, what you required to do is to modify the my node and linked nodes definitions define these to be classes. So, that we can represent graphs with weights or nodes and edges and what I want you to do is I want you to make all the data members private in both of these classes right. So, the weight of a node cannot be accessed directly from the main program the weight of an edge should not be directly accessible from the main program the ID of a node should not be accessible directly from the main program the list of incoming edges list of outgoing edges nothing I want all data members to be private ok. So, you have to modify these definitions clearly we will need to add some additional members right at least need to store the weight of a node I need to store the weight of an edge and so on, but I want all data members to be private no data member should be public I should not be able to access them from the main function how am I going to access them through appropriate member functions with appropriate access control ok. So, we want you to redefine that structure as a class where all data members are private and you have to add new member functions. So, that you can do whatever operations we were doing earlier you know reading in a graph initializing the graph. So, here is what I want to do. So, this is the same main program as before where I am allocating an array of nodes I read in the number of nodes allocate an array of nodes if it is null I say memory allocation failure and last time we had init nodes here now I have used new init nodes which is going to take the nodes array going to take the number of nodes and now since each node has a weight. So, within new init nodes you can ask the user for the weight of node 1 the weight of node 2 whatever right and it should go ahead and initialize all of the nodes in the array should set the ID right should set the weight right the incoming and outgoing right, but remember all of these are private data members you cannot access them directly from either the main function or from this function you have to access them through interfaces or through member functions. So, you have to write those member functions and then this is just like what we had last time we were reading in edges one at a time saying give start of edge give end of edge now I will also say give weight of edge and then instead of ad edge I will say new ad edge which takes the nodes array start edge end edge weight and it must store the information about that edge from where to where what is the weight of that edge, but once again all data members are private. So, you have to use appropriate public member functions to set the values of private data members and finally we want to you know last time we just printed out the set of incoming nodes and the set of outgoing nodes of every node here I want to calculate some metric for node and that could be some of in edge weights minus some of out edge weights divided by node weight. So, I want this to be a public member function of my node such that I can call this on each nodes I and should print out that metric is this clear. So, so your task like last time is to write these three functions. So, these are very similar to what you did in last class except that now there is I want weights on nodes weights on edges and more importantly I want all data members to be private. So, you have to write some member functions to be able to access those private data members the accessor functions mutator functions that we just saw you have to write some member functions to do that is this clear is the problem clear very similar to the last problem, but now I am putting some access control on it. So, try this you can start from these structures call them classes and build on top of those has anybody done this completed it here is Anuj's solution can't project that here. So, what he has done is he has said plus my node int id load weight linked nodes outgoing and incoming this part I believe for all of you got I mean if you did not get even this part then there is a problem when we are just trying to add a we are trying to remember a weight along with each node. So, we have to add a data member called weight I mean weight or whatever your favorite name is and because this is a class these are automatically by default private right and then there have to be some public member functions some public member functions and how will linked nodes look like. So, Anuj has defined it like this class linked nodes is how the member functions for linked nodes with the data members is a int node id load edge weight linked nodes next and then there are some public data members right. So, basically it's like the previous one except that now he has added something to keep track of the edge weight and there are they will have to be some public member functions. So, let me just try to illustrate what Anuj is trying to do. So, suppose I have a graph like this. So, let us say this is node 0 this is node 1 this is node 2 and let us say I have some edges like this and let us say the weight for this is 2.1 the weight for this is 5.2 the weight for this is 3.7 and the weights for these edges are let us say 4.1, 3.9 something 0.3. So, what you know Anuj's scheme seems to be is that this graph is going to be represented by an array of size 3, 3 nodes an array of size 3 where each element in that array will be of this class right. So, it will have an id data member of weight data member and some outgoing and incoming data members and then there will be some member functions. So, these are all member functions right. So, how is this going to look like? So, it will have some id it will have some weight this is the nodes array. So, this is nodes this is nodes 0 this is nodes 1 this is nodes 2 each nodes thing each element in the nodes array is an object of this class. So, it has id weight outgoing incoming. So, I am going to write it like this id weight and then outgoing and incoming each element will have this right id weight outgoing incoming id weight outgoing incoming and now the ith entry in this array should represent the ith node. So, here I really want to say id 0 id 1 id 2 weight this should be 2.1 this should be 5.2 and this should be 3.7 right this is representing the first node whose id is 0 weight is 2.1 this is the second node id is 1 weight is 5.2 id is 2 weight is 3.7 and now I will have to represent the outgoing edges from node 0 there are two outgoing edges from node 0 right. And so, these can be thought of as a chain like this remember the outgoing and incoming are pointers to linked nodes right and linked nodes has a node id and edge weight and a pointer to another linked nodes right. So, that is what we are going to use. So, outgoing is a pointer to linked nodes and this can store a node id it can store a weight and it can store another pointer to an object of linked nodes type right. So, in the id what should I store from 0 I have an edge going to 1. So, I will store that there. So, this is now representing that from 0 there is an outgoing edge to 1 what is the weight of that edge 4.1 and this is saying this is the next element in the list of outgoing nodes right. So, there is another outgoing edge here. So, from 0 to 2 weight is 3.7 and there are no further outgoing nodes. So, this is none. So, I would really like to store it this way right. And of course, in the incoming one I should say that for 1 there is an incoming node from 0 whose weight is 4.1 and there is for 1 there is another incoming node from 2 whose weight is 3.9 incoming edge from 2 whose weight is 3.9 and finally this is none right. And from 2 similarly there are 2 incoming things. So, I should have something from 0 weight 0.3 pointing to the next thing 1, 1.1 and this is none. So, and of course, there will be other things here you know I think 1 has 1 outgoing edge. So, that is going to 2 has weight 1.1 and only 1 outgoing edge and similarly 2 has 1 outgoing edge. So, 1, 3.9 and 9. So, this is the representation this is how I want to represent the graph right. Last time what we had we did not have this weight and here when I was storing the information about the edges I did not have the weights of the edges. But other than that everything is more or less the same. Is this clear how the graph has been represented? I mean that graph I want to represent like this and now the question is that. So, you know so these data members that Anuj has used are indeed correct I mean they are certainly in the right track. Now you have to write appropriate member functions because all of these are private. So, you cannot access them from outside. So, you have to put appropriate public member functions which when you are trying to initialize a node it will go ahead and set the ID set the weight maybe set all of these to null. Then when you are trying to add an edge the public member function should go and add to the appropriate outgoing and incoming lists right. So, you have to write appropriate accessor and mutator functions for both the class my node and the class linked nodes. So, that finally this graph as you read in the edges and read in the weights of the edges and the nodes can be represented like this. Is this clear? So, you know the data members are right here now you have to put the appropriate public member functions because all of these are private. In a class if you do not declare anything everything is private and we want to keep them as private that is the whole purpose of this question. Now you should write appropriate member functions. So, that you can do all the manipulations you want on the appropriate data members and from the main function there are those new init nodes will be called and that should ask for the weights of the nodes and initialize them new add edge will be called and finally print metric will be called. This print metric should be easy because this is a member function of the node and a member function has access to all the data members in that structure. So, it can just go through the outgoing list add up all the edge weights go through the incoming list add up all the edge weights and do all of this division and print it out. So, I would like all of you to do this you know I have sort of almost shown you how to do it just try to appropriate member functions as that nobody needs to access the data members directly and you know try it out program it on your computer when you come to the lab or in your laptop and see what is happening ok.