 So, what we are going to do is we are going to continue our discussion about structures and you know so far what we have seen about structures is that there are groups of variables or groups of variables and arrays that we want to put together, keep together and we sort of put all of them in a structure and then we could use objects of that structure type wherever we wanted. So, what we are going to see today is that not only can you group variables or arrays together in a structure, you can also group functions together in a structure and that sort of gives you a new way of programming at least an additional feature to use while programming. So, in order to illustrate that we are going to take this example that we want to write a program to reason about motion in three-dimensional space. So, we are going to have three-dimensional vectors representing position, velocity, acceleration and similar things. So, we will have three-dimensional vector as a basic object, we want to have a structure for three-dimensional vector and then we want to see how to define functions which operate on these three-dimensional vectors. So, of course a three-dimensional vector can be represented in several ways, we can have a Cartesian coordinate system, we can have a spherical coordinate system, cylindrical coordinate system. So, for simplicity we will use the Cartesian coordinate system, but later on we will see that it you know if you did the programming right then it is not too much of an overhead trying to move from one representation to another representation from Cartesian to cylindrical for example. So, with the Cartesian coordinate system I have three data members which are the X, Y and Z coordinates and let us say we want to write these functions, we want to take two vectors, three-dimensional vectors add them, we want to scale a vector by a constant, scalar constant, we want to find the Euclidean length of a vector and so on. And so here is a simple function that adds up two vectors. So, A and B are references to objects of type B3 and I have put const here to indicate that these objects cannot be modified within the function, they are parameters which are read only, you cannot write anything to those parameters. And then here we have done the simple thing right, I mean just added the X coordinates, Y coordinates, Z coordinates and returned an object of type B3. So, this is fairly straightforward. Similarly, we can do scaling just take each of the coordinates, multiply them by a factor, you are done. And the length is also you take the coordinates, square them, add them up and then take their square root. So, the square root if you recall you know towards the beginning of the course we had sort of written our own function using loops to compute square roots at least integer square roots. But you can also use some libraries for example, the CMath library gives you the square root function. So, this is just to say that you know we can apply operations on whatever we are computing here. So, one thing that you might note in these three functions is that at each of them there is an object A of type V3. And I am doing some operation on that, here I am adding an object B of type V3 to it, here I am scaling that object A of type V3 by a double factor, here I am finding out the length of the object A of type V3. So, in some sense all of these operations are being performed on an object A of type V3 and of course that can take additional parameters like here it can take another object B of type V3 or a constant factor and so on. So, if you observe this you know sort of this feature that each of these functions requires a vector and then it does something on that vector perhaps by using some other parameters. So, one question that one might ask is why not associate these functions straight away with this object A. So, instead of saying sum A and B can I say that the sum function is associated with the object A and if I want to add something to A I will call the sum function associated with A and I will simply pass whatever I want to add to A. Similarly, if I want to scale the object A I will call the scale function associated with the object A and simply pass the scaling factor to it and of course if I just want to calculate the length I do not need to pass any parameter I can just call the length associated with the object A. So, it is more like saying that you know there is something that I am doing with the object A in each of these functions. So, why not associate these functions with these objects themselves? So, that you know this kind of defines an interface for interacting with the object A. So, what do I mean by an interface? So, I will go back to that analogy of a television set. So, if you have a television set there are lots of electronic circuitry inside, but if you want to change a channel you just go to the knob and just whatever turn it or you take the remote and just press some switches and of course that action causes a lot of things to happen inside and as a result the channel changes, but really that is the interface by which you are interacting with that object. So, it is kind of like a function that the object provides you and you can use that function perhaps pass some parameters to it you know which button of the remote you are pressing or what sequence you are pressing and that ends up doing some taking some effect on that object some something happens with that object. So, we want to view these functions in a similar manner that these are kind of interfaces for interacting with the object A if I have an object A and if I call the sum function associated with it it will do something with that object A and in the process of doing something it can take some additional parameter and then do that operation. So, C++ actually allows you to do this you can have what are called member functions I mean these x, y and z by data members. So, just like them I can have member functions. So, here I have this is a member function. So, if you see how the member function is written it is just like any other function right there is a return type name of the function in this case it does not take any parameters and then there is some body of the function and it is returning something. Similarly, this is another member function whose return type is v3 which is the same struct that I am trying to define and it takes some parameter does something and returns that and similarly for scale right. The interesting point to note is that these function definitions are within the structure definition. So, essentially these are functions associated with that structure whenever you declare an object of that structure type v3 you can call these functions on that object right. So, these are functions which are going to be associated with every object of structure v3 and the other thing to note is that here you know in this function I am saying x times x plus y times y plus z times z this x y and z really refer to the data members of the structure. So, if you look at this function this function does not take any parameters there are no declarations of x y z over here. So, what are these x y z these are the data members of the parent structure right. So, this is the nice part about member functions is that you have free access to the data members of the parent structure and you can do whatever you want just like any other function and you can return the appropriate thing. So, for example, in this function I am accessing the data member of the parent structure and I am also accessing a data member of a parameter pass to me and I am updating some data member of a locally allocated a local variable within this function right. So, you have local variables just like normal functions your parameters just like normal functions in addition you have access to these data members of the parent structure is this clear right. So, these are called those are data members and these are called member functions they just said and this is I just explained this is accessing a member of the parent object of this types of the structure type and this is accessing a member of the parameter that is passed. So, if you recall how did we access data members of a structure using the dot and the arrow operators right. If I had an object P of type P3 I could use P dot x to access the data member x and if I had a pointer to a object like pointer P is ampersand P. So, basically this contains the address of P. So, pointer P points to the object P which is of type P3. So, if I am using a pointer I can use the arrow operator. So, this is saying dereference pointer P and in the object that you get access the member x this is how we access data members. So, we are going to access member functions in exactly the same way. So, for example, here P is an object of type P3. So, I can access the data members by saying P dot x, P dot y, P dot z. I can access a member function scale by saying P dot scale and then I can provide the parameters of this function. It is just like invoking a normal function except that this is a member function of a particular structure and I am taking an object of that structure type using the same dot operator like I used to refer to data members and I am referring to member functions. And similarly for pointers, if I have a pointer I will use the arrow operator to refer to member functions just like I used the arrow operator to refer to data members. So, the two ways. So, the other thing to remember is that so when you are calling this member function it is in the context of a specific object of that structure type. So, that object, basically the object whose data members you have free access to that object is also called the receiver object. So, here scale is the member function called on the receiver object P with the parameter 0.5. And of course, depending on what that scale function is it will do whatever it does in return. And similarly we can use the arrow operator also. So, this is a pointer to the receiver object and this is accessing the member function through the arrow operator. So, are there any doubts about this? I mean this is just saying that member functions can be accessed just like data members and you can pass parameters to them, you can have some local variables in them, you can refer for free the data members of the parent structure. Is this clear or some doubts? So, what we are going to do now is we will try to write a simple program that uses member functions. So, we have just seen the structure V3. So, we want to write a simple motion simulator where given the initial position and velocity of a solid body as three-dimensional vectors, we want to calculate and given the acceleration also of the body as a three-dimensional vector and we will assume that this acceleration does not change with time. We want to basically find the positions of this object every delta units of time for an entire duration of T units of time. So, this total lapse time is T granularity of simulation time is delta, we want to find the positions every delta units of time. Is this clear what we are trying to do? So, we will take the same structure that we had defined earlier. We had seen these three member functions, some scale and length. We are going to add one more member function to it called print which just prints out the different data members. So, any member function has access to the data members for free. So, it can just use those in the statement and print it out. And then here is how the motion simulator program might look like. So, I have three variables of type V3, three-dimensional vector. This is the initial velocity acceleration and initial position and then this is the delta T which is the granularity of time, granularity of simulation time. This is the total time and I will use T to denote the current time. The time will have so far and that is initialized to 0. And then I read in the x, y and z components of the initial velocity. Note that I am directly accessing the x, y and z data members of the object U. Similarly, I read in the x, y and z components of acceleration and I should also read in the x, y and z components of the initial position. So, that is missing here. And then I read in the total time and the simulation time granularity and all of that. I do some sanity checks if total time is less than 0 or granularity is less than or equal to 0. I say invalid input and then I do here is the main simulation loop. So, within this loop what do I do? I basically use this well-known equation that the displacement is given by u t plus half a t squared where u is the initial velocity and a is the acceleration. So, in our case u is a vector, a is also a vector and t is the scalar. So, how are we going to compute this as a vector quantity? So, we will say that take the vector u, scale it with t. Scale is a member function of structure v 3 and u is an object of that type. So, this is saying take u which is an object of type v 3 and invoke the member function scale on that receiver object with the parameter t. And here I am saying take a as a three-dimensional vector, scale it with 0.5 t squared. So, this is going to return me a vector, that is going to return me a vector. I take this vector and call the member function sum on that vector. Is that clear? What is happening there? So, I am basically using the member functions. I take the object u and I want to scale it with t. So, I call the member function scale of the object u past the parameter t with it. And it returns me a three-dimensional vector which is u scaled by t. Similarly, a times half p squared. And then I take this vector which is returned and I call the member function sum on that return vector with this as the other parameter. So, this will add this vector to whatever is returned by this u dot scale t. And that vector that is returned I am going to store it in this variable current displacement of type v 3. And to finally find the current position I am just going to add current displacement to the sum. I could also do s dot sum current displacement or I could do current displacement dot sum s. Saying take an object, invoke the function sum on that and pass the parameter and then it will do some operation and return the resulting vector. And then finally, I use the print function to print it out. So, I say at time t the position is current position dot print. So, that will just print out the x, y and z coordinates of current position. And then I increment t by delta t and go back and keep looping. It is fairly straightforward. But I hope what you see is that I am actually making use of member functions of objects of type v 3 in some nested way here. I called scale on a and on the resulting thing, the resulting thing I am using as a parameter and here I called scale on u and on the resulting thing I am calling sum. So, I could of course, store those in intermediate temporary variables and then do that, but I could do this also directly. So, I hope are there any questions about how to use a member function on a receiver object? So, a is a vector, a is an object of type v 3. Scale is a member function of the structure v 3. So, let us look at, this is the structure v 3. This is the scale member function. So, when I call scale, it will do all of this computation until return me an object of type v 3. So, when I say a dot scale, this function is called on the object a which is of this type. And what will that function call do? It will allocate a new variable v of type v 3. It will set v dot x to, this is x of the parent object. So, I had called a dot scale. So, the parent object was a. So, this will take the x coordinate of a, multiply that by 0.5 t squared because this is the parameter 0.5 t squared have passed to scale. 0.5 t squared is what have passed as parameter to scale. And this is the receiver object or this is the parent object on which I have called this member function. So, that is exactly what is going to happen. So, 0.5 t squared is coming here. The x that I am referring to is the x of vector a. So, basically x coordinate of vector a multiplied by 0.5 t squared is assigned to v dot x where v is a local variable that is declared here in this function. Similarly, for y and z and finally, I am returning v. So, I am returning that object of type v 3. So, when I call a dot scale 0.5 t squared it is going to return an object of type v 3. Similarly, u dot scale t will return an object of type v 3. If I am returning an object of type v 3 that object has a member function sum. Every object of type v 3 will have a member function sum because struct v 3 has a member function sum. So, u dot scale is returning an object of type v 3 and because every object of type v 3 has a member function sum. So, whatever u dot scale is returning I can call sum the sum member function of that object. Is that clear? I mean you could also do it by saying that assign a temporary variable of type v 3 to be u dot scale t and then it called the temporary dot sum something that is also possible. You have sort of skipped the temporary. Is that fine? So, one thing that you might have noticed you know as we are discussing these structures with data members and member functions is that there are absolutely no restrictions on from where you can access which data member or which member function. You can access the data member, any data member of any object or any member function of any object from anywhere in your program. There are no restrictions at all. I could just say p dot x anywhere in my program and I have access to data. So, there were no restrictions and it turns out that sometimes you do want to put restrictions on who can access what from which part of the program and you know once again going back to the television example. I mean inside the television probably there are lots of internal circuitry which you do not want the user of the television to be necessarily aware of and certainly you do not want the user to have access to those. You want the user to access the television through a remote control or some switches on the front panel of the television and internally those things are going to you know whatever change the resistances, capacitances, change some signals to some electronic circuits inside. But you do not want the user to basically get access to those. So, therefore, you know when we are designing complex objects it is often a good idea to hide the details of the object and to present as an interface a simple interface which others can use and when they use that through that interface some changes happen to those internal details. So, that is the same thing that we want to do here that when we are going to define structures maybe that structure is a very complicated one. For example, three dimensional vectors we chose to use the Cartesian coordinate system. But if I am using three dimensional vectors to solve a physics problem why should I be bothered about the fact whether Cartesian coordinate system is being used or some other coordinate system is being used. I just want to do vector addition vector scaling finding the length of a vector. So, the internal details you probably want to hide from the user and you want the user to access the internals only through some very well defined interfaces. So, those interfaces are going to be the member functions and the details that you want to hide or abstract away you would not like anybody to be able to access those details just by saying p dot x if you really wanted to hide x. So, if you want to you know hide some things and expose some things therefore, we need a mechanism for doing that currently the way we are dealing with structures is any data member any member function can be accessed from anywhere in the program. Any data member of any object any member function of any object can be accessed from anywhere in the program. If you want to do you know more fine grained control of it then C++ actually provides this mechanism where you can use these keywords called private public and protected to declare which member functions or which data members are to be accessed in what way. Now in our discussion we will not probably have occasion to discuss protected because this requires discussing some more things and I do not think we will be able to reach there. So, we will just discuss private and public. So, if you declare a data member or a member function to be public you know it is saying that it is for the public. So, everybody can use it from anywhere in the program. Whereas if you declare a data member or a member function as private it means that nobody can use it from anywhere in the program but only the member functions of the parent structure can use it. So, remember all of this is within a structure. So, if you declare a data member of a structure as private it means nowhere in the main program can you access the data member. However, the member functions inside that structure can access the data member. The member functions always have access to all the data members. So, for example here in the struct v3 that we had seen earlier everything was accessible from everywhere which means that everything was public. All the data members all the member functions could be accessed from anywhere in the program. So, they were all public and in fact you know if you declare a structure if you define a structure and if you do not explicitly say which is public or private everything by default will be taken as public. So, whenever you are defining a structure and not specifying explicitly what is public what is private by default everything will be taken as public. However, you can specify that there is some part of it which is private the rest of it which is public. So, for example here x, y and z the three data members are private which means that from the program you cannot directly say u dot x u dot y u dot z because the program cannot access private data members these are like the circuits inside your tv to which you do not have access to. If they are declared as private the external world does not have access to those whereas these member functions are public which means if you declare an object of type v3 then you can call these member functions on that object, but you cannot access these data members directly for that object. So, that is the difference between private and public and of course you could have blocks of private and public and private alternating like this. So, once you write private until you see the next public everything is private once you write public until you see the next private everything is public and so on. So, here there are three private data members one private member function and two public member functions is that clear? Yeah. So, this is saying that this is private to this structure in the main program. So, remember in the main program we had used things like this velocity dot x velocity dot y velocity dot z where velocity was an object of type v3 right. Here I am directly accessing these data members of this object of type v3. If you declare it as private you cannot do that anymore from the main function you do not have access to velocity dot x it is like your television and you are trying to access some circuit inside, but you do not have any way to access that right no, but these are the member functions of the same structure. See member functions of a structure are defined within the structure the main function is outside from the main function you cannot access any of the private members, but the member you know this is like saying this is my TV these are the internal circuitry of the TV these are the external interfaces. So, of course, the external interfaces will have access to the internal circuitry it is just that somebody outside like the main function will not have access to the internals. So, as I said private members can be accessed only from member functions of the same structure. Member functions of a structure have unrestricted access to everything within that structure. If you are trying to write a member function for a structure you can access everything within that structure, but in the main function or in some other structure can you access the private members? So, the answer is no you can only access the public members you know we are basically trying to encapsulate things we are saying a structure is one object we are putting some boundaries we are putting some hiding mechanism and of course, inside that the member functions can access everything, but from outside that you cannot access everything you can only access whatever is declared as public. Did that make sense? So, do you see the difference between a main function which is not a member function of any structure the main function is not a member function of any structure it is not defined within a structure definition and a member function a member function like sum this is defined within a structure. A structure was a group of variables and arrays put together now we are saying that there are also some operations I can do on this which are those member functions, but those are specific to that structure the main function does not belong to any structure it is just the program that you are writing. So, in the program that you are writing you cannot access any private members, but from the member functions of a structure you can access the private members. So, what it basically means is that from the main function you should access the public member functions and the public member functions will go ahead and access the private data members which is exactly how you operate a complex object like a television or an air conditioner or whatever. From the outside world you only have a fixed set of things that you can do and when you do those things they go and access the internal circuitry you cannot directly access them this is exactly that mechanism. So, in C plus plus actually there is something almost like a structure that we use very often which is called a class. So, for your purposes you can think of a class as just like a structure with this only difference that of course we use the keyword class instead of struct and in a structure everything is public by default in a class everything is private by default. If you do not specify public or private inside a class it means that everything is private by default. So, for example, here is the class v3 and I have declared x, y, z as private, but even if I did not put this private here by default things are private inside a class. So, x, y, z would continue to be private and then these are the public member functions. The rest of it is just exactly like what we have studied about structures. It has data members, it has member functions, public, private, parameters everything. So, as I said if you if in the class v3 you declare x, y, z as private it means you can access x, y, z only within these member functions you cannot access them in the main program. So, if I try to write read in velocity dot x velocity dot y velocity dot z the compiler will say you are trying to access a private data member of the object you cannot do that unless you are within a member function of that object. So, this of course, create some problem is that you know then how are we going to read and write private data members of a class. So, one option is to make all data members public, but that is clearly not what we want to hide something and we want to give access to only some of the members. So, we should not try to make everything public and you know I mean this is kind of the problem that happens if you try to make everything public. So, look at our look at this class definition this is the same class v3 and suppose I had declared x, y, z as double data members all of them public. Now, because these are declared as public in the main function I could directly read in velocity dot x velocity dot y velocity dot z. But suppose at a later point of time I you know I decide to implement the class v3 I decide to represent three dimensional vectors not using Cartesian coordinates, but using cylindrical coordinates. So, then I will use rho phi and z to denote the same three dimensional vector. But because in the main function I have read in x y and z directly therefore, this is not going to work with this changed class definition. So, you know the sequence of things is that I first defined a class then I wrote a main function and because something was declared public here I went ahead and freely accessed those. Later on I come and change something in the class now I have to go back and change everything when that class was used because if I have changed something public in the definition of the class then these might have been accessed elsewhere and have to go and change everything. So, now instead of reading x, y, z I must read rho phi and z and this is bad because all I was trying to do is I was just trying to change the representation of the three dimensional vector and now all places where three dimensional vectors have been used probably needs to be changed. So, what we should do instead is that we should probably hide the internal representation of the three dimensional vector. We should not let the main program directly have access to x, y and z components. If it needs to know the x, y and z components it should call appropriate member functions which can return the x, y and z components because then I can go from one coordinate system to another coordinate system much more easily. So, as we will just see so for example, instead of allowing access directly to x, y, z suppose I declared these member functions saying get x, get y, get z and they just return x, y and z. So, here I do not have direct access to these but I can call these functions and get the values. And similarly if I have a member function set x, y, z it can take the values of x, y, z and set them here. So, you might be wondering you know why are we doing this in a roundabout way if I really want to set the values of x, y and z or read the values of x, y and z why not permit direct access to those members. And the reason is this is that now if I decide to change this from Cartesian to cylindrical coordinates, all I need to do is I need to say that okay now my class definition is going to look something like this rho, phi and z. I will just change the definitions of these functions instead of get x returning x I will make get x return rho times cos phi instead of get y returning y I will make it return rho times sin phi instead of set x, y, z directly setting the values of x, y and z I will make it set the values of rho, phi and z. So, the external world which was using only these functions get x, get y, get z and set x, y, z does not see any change at all. It sees the same interface it is providing the same x, y and z but internally it is being stored in a different way just by changing these member functions here. So, now if I had used a representation like this and if I were trying to write a program like this I would not have written directly read in velocity dot x velocity dot y velocity dot z I would have said read in x, y and z and then call velocity dot set x, y, z and I can continue to use that whether I am using partition or cylindrical because set x, y, z when I go to cylindrical just does the necessary conversion within itself the main function does not need to worry about it. So, this is why you know if you are defining a class and if your friend is using it or if your teammate is using it it is best to make the interfaces very clear. So, that all your teammate needs to know is what are the interfaces, what are their effects does not need to know anything about how internally things are being represented and you can go ahead and change those representations without affecting any of the code that your team members are writing because they are just using the interfaces and you present the same interface. Internally what you do is what you change inside the class definition and you know these things which are called accessor and mutator functions. Accessor functions allow you to access private data members or other data members and mutator functions allow you to mutate or change private or other data members. The person who is defining this class defines what data members will be accessible what data members will not be accessible. So, provides the appropriate accessor and mutator functions. Is this clear? Okay.