 Hello and welcome back. In this session we are going to see a few more features of inheritance in C++. Here is a quick recap of what we studied about inheritance in the last couple of lectures. We studied about inheritance with public, private and protected members. We also saw that inheritance or derivation can be done in three different modes public, private and protected. And we also studied about access control in these derived classes. How to access data members and member functions in these derived classes. In this lecture we are going to see how we can redefine member functions of a base class inside a derived class. We are going to see how to access methods of base class from within the derived classes. We are going to study about constructors for derived classes and also their destructors. And then we will see a very interesting concept of how assignment operators are treated in a very special way when we talk about inheritance. Much of this lecture is motivated by the treatment in the book and introduction to programming through C++ by Aviram G. Ranade published by McGraw-Hell Education 2014. Some examples used in this lecture are taken from this book. Now recall the bank account hierarchy that we have studied earlier and let us say we are only going to look at this part of the hierarchy where there is a base account and there is a special kind of base account called a savings account and there is another special kind of base account called the current account. And the base account has three data members ID, balance and name and it has a member function called print info. The savings class which is derived from the base class has two additional data members age and ATM and it also has a member function named print info. Note that the name of this member function in the derived savings class is the same as the name of this member function in the base class and similarly the current class which is derived from the base class has two additional data members amount and overdraft and it also has a member function print info which has the same name as the member function or method in the base class. So here is how the base class might look like let us say this member function print info just prints the following statement printing in base and then it also prints the ID and balance which are data members of the base class. Now let us look at the savings class which is derived from the base class and here I have this member function print info which prints printing in savings and it outputs the value of the age and ATM data members which are additional data members of the savings class. These two data members are not present in the base class they are additional data members in the derived class and let us also look at how the class current might look like that is also derived from the base class it has two additional data members amount and overdraft and here is the member function print info for the current class this prints printing in current and it outputs the value of the two additional data members in this derived class named amount and overdraft. Now that we have these class definitions and the definitions of the method print info in these three classes we want to see what is going to happen if I execute this program. So here I have declared three objects AC1, AC2 and AC3, AC1 is of the type base class AC2 is of the type savings class and AC3 is of the type current class here I am doing some initialization of the data members ID and balance of all of AC1, AC2, AC3. Now AC2 being of the savings class has a couple of additional data members so I am initializing those over here and similarly AC3 being of the derived current class also has some additional data members so I am initializing those here. Now I want to call print info of the base class, print info of the savings class and print info of the current class and I want to ask what is going to get printed. So let us see here is what the program will output when I call print info for AC1 which is an object of the base class the method print info in the base class is invoked so it is going to print printing in base and it is going to print the values of the data members ID and balance of AC1 in this case there are 1 and 15,000. Now when I call AC2 print info then the method print info has been redefined in this derived class and this redefined definition of print info is going to take effect. It is not the print info in the base class that is going to get executed because it has been redefined in the derived class this redefined method is going to get executed. So when I call AC2.print info it actually says printing in savings and it gives the value of age and ATM of AC2 in this case it is 19 and 240. Similarly when I call AC3.print info since print info has been redefined in the current class which is derived from the base class. So it is not the definition of print info in the base class that is going to take effect but it is the definition of print info in the derived class which is going to take effect and so here I will see printing in current and then it will also print the values of amount and overdraft as in the object AC3 and they are respectively 1000 and 5300. Note that if the current class did not redefine the method print info then when I call AC3.print info it would inherit the print info method of the base class and it would then print printing in base and the values of ID and balance of AC3 in this particular case 3 and 4500. But since I have redefined print info in the current class this redefined definition of print info is going to take effect when I call it here. So this is sort of summarizing what we have seen there but what if I wanted to do the following that in the method print info which I am redefining within the savings class or which I am redefining within the current class. Suppose I also want to print the values of ID and balance and I want to do that by invoking the print info method of the base class. So this is a very interesting situation I have redefined print info in the derived class but then I also want to use the print info method of the base class how do I do that. So well in C++ there is a simple way to do that what we have to write here is that I want to invoke the print info function of the base class and here I have to say I want to invoke the print info function of the base class this double colon here is the scoping operator in C++ and this says that I am calling the print info method in the scope of the base class and not the current print info method here. So note that the print info method of the savings class is actually invoking the print info method of the base class and then doing some additional stuff and similarly the print info method of the current class is invoking the print info method of the base class and then doing some additional thing here. So this is what you need to do you need to use the scoping operator and say that you want to invoke print info of the base class if you have redefined print info in the derived class but still want to access print info of the base class. So in this particular case let us see what would get printed when these three statements are executed. So of course the first one will still print the same thing as before in the second case it will first invoke print info of the base class. So it will print printing in base and then print the values of id and balance of ac2 which is 2 and 6700890 and then it will also print these which is printing in savings and the values of the data members age and ATM of ac2 which is 19 and 240. And similarly when I invoke ac3.print info it will first invoke print info of the base class so it will say printing in base and the values of id and balance of ac3 which are 3 and 4500 and then it will additionally execute these statements and it will print printing in current and the amount and overdraft is 1000 and 5300 as initialized here. Now we all know that when an object of a particular class is instantiated the constructor for that class has to be invoked. Now when we have classes which are derived from base classes and when I am instantiating an object of the derived class then well I am also instantiating an object of the base class because an object of the derived class also contains everything that the base class contains. So the question now is how are the constructors of the base class and the constructors of the derived class going to be invoked when I instantiate an object of the derived class. So let us see it through this example. So in this example I have a base class and this is a default constructor of the base class you would recall from earlier lectures that a default constructor is 1 which does not take any arguments. So in this case the default constructor just prints default constructor base and initializes the values of the data members ID and balance to 0 and 0.0 and the derived class savings has also a constructor but this is not a default constructor it actually takes two arguments and once again you will recall from your earlier lectures that when I have a constructor which takes arguments I can actually use an initialization list to initialize the values of various data members in terms of expressions on these arguments. So here I am initializing the value of h to x and I am initializing the value of atm to y and then I am also printing out the statement derived constructor and here is a little main program in which I have instantiated an object of the base class invoked a method of that object then instantiated an object to the savings class with some parameters to be fed to the constructor of the savings class and then invoked a method of the savings class. So we want to see how these would get executed which constructors would get invoked and in what sequence would they get invoked. So well when I declare an object of this base class then the constructor of the base class has to be invoked so that is what happens I invoke the constructor of the base class and that goes ahead and executes these statements that are now highlighted in blue and that is going to print default constructor base after that I am going to execute the method print info of this object AC1 so this method is going to get executed and when these highlighted instructions are executed I will see this on the output printing in base and then the values of id and balance for AC1 which were already initialized to 0 and 0. Now after that I have these two statements here which are assigning values to some local variables inside the main program and then I have the statement which is instantiating an object of class savings with these parameters. So as a result the constructor of savings is going to be called with these parameters however note that an object of class savings is really an object of class base plus something else. So the constructor for the class base must also be called and indeed that is what is going to happen so when the constructor for the class base is called I am going to again see default constructor base being printed out these data members will be initialized to 0 and 0 now these data members are for the object AC2 which is of the derived class savings and then after the constructor of the base class is done then we will have these other actions for example here initialization of the values of age and ATM with the values of the parameters and then this statement inside the constructor of the savings class is going to get executed. So as a result I will see derived constructor over here and then the constructor for savings is done and so then I will go ahead and execute AC2.printinfo which is going to execute these statements and as a result it is going to print printing in savings and then the value of age and ATM and what are the values of age and ATM they were initialized here in the constructor for savings and what were they initialized with the values of X and Y and these are the values of X and Y that got passed. So age will be 20 and ATM will be 240 which is what is printed out over here. So this shows how really when you instantiate an object of a derived class an object of the base class is also instantiated and therefore the constructor of the base class will be called and then the constructor for the derived class will also be called. Here is another example where we have pretty much tried to do the same thing but here the base class does not have a default constructor it has a constructor with a parameter with an argument and once again I have a main program which is instantiating an object of the derived class and these are the arguments to the constructor of the derived class. So let us see what happens we want to ask is this program going to compile well when I am instantiating an object of this derived class I have to invoke the constructor of the derived class but then an object of this derived class also has an object of the base class plus some additional things and therefore the constructor of the base class must also be invoked unfortunately we have not specified a default constructor for the base class so in order to invoke a constructor of the base class I have to specify an argument to the constructor here when the constructor for the derived class is invoked I have not specified here how I am going to invoke a constructor of the base class with what argument so therefore there will be a compilation error the constructor of the derived class needs to invoke the constructor of the base class but I have not specified how to provide the argument to the constructor of the base class and the base class does not have a default constructor so therefore the constructor of the base class cannot be invoked and I will get a compile time error as I said we expect the base constructor to be invoked with an argument and that is not specified here these are just the initialization lists of these data members it is not specified here how to invoke the constructor of the base class so therefore there will be a compile time now in this case we have tried to do the same thing as before the base class does not have a default constructor it has a constructor with an argument in the derived savings class the constructor for the this derived class actually specifies how to invoke this constructor of the base class with what argument and then it also has this initialization list so note that these look very similar but this is really an invocation of the constructor of the base class with the argument x whereas these are initialization lists where I am saying the data member edge is going to be initialized with the value of y and the data member ATM is going to be initialized with the value of z so although they look similar they are actually serving two very different purposes and of course the body of the constructor I can have some executable statements. In the main program here I am instantiating an object of class base providing one as the argument to it so this constructor is going to get invoked that is statement is going to get executed and in the output I will see default constructor colon base and the data member ID is going to be initialized with the argument a in this case one and the data member balance is going to get initialized with 0.0 then when I invoke the method print info of the object AC1 these instructions are going to get executed so it will print printing in base 1, 0 1 being the value of the data member ID for AC1 and 0 being the value of the data member balance for AC1 as initialized here. After that we have the statements which are assigning values to some local variables and then I am instantiating an object AC2 of class savings now this class savings is a derived class so its constructor is going to get invoked which in turn is now going to invoke the constructor of the base class and here I have specified what argument to provide to that constructor so here I have provided ID age ATM which is 10, 20 and 240 and so now the constructor of the base class will be invoked with the argument 10 as a result it is going to print default constructor base initialize ID to 10 and balance to 0 and then it is going to return and when it returns it is then going to proceed with the rest of the constructor for savings so it will initialize the data members age and ATM to the values of the parameters y and z in this case 20 and 240 and then it will print derived constructor which you should be able to see in your output and finally when I call print info on the object AC2 I am going to come and execute these instructions so it will say printing in savings and then it will print the value of age and ATM which were initialized here to the values of y and z which is 20 and 240 in this case so once again this shows the sequence in which constructors of derived classes and base classes are invoked here is yet another example where we have initialized data members of the derived class in the body of the constructor of the derived class instead of using initialization lists so we have the same sequence this constructor being invoked for the base class these statements being printed then when I invoke print info it executes the statements prints out these two lines over here then some local variables being assigned and then this object of class savings being invoked this goes and invokes this constructor which invokes the base constructor with a specified argument which goes ahead and prints this statement and does some initialization of data members returns back here and now there are no further initialization lists so it executes the body of the constructor for savings which assigns the values of y and z to age and ATM respectively and finally it prints derived constructor and after that print info is going to print these two lines as before so well we have seen how constructors get invoked when I am instantiating an object of a derived class what happens with destructors well there is a general rule of thumb here that if I have a class which is derived from another class which is again derived from another class which is derived from another class and that is derived from another class then the constructors are going to be invoked in this way the top most base classes constructors going to be invoked first then the derived class under that then the derived class under that and so on that is the sequence and the destructors are going to get invoked in exactly the opposite sequence which means the destructor for the class lowest in the class hierarchy is going to get invoked first then the destructor of the class above that the base class for that then the destructor of the base class for that and so on so that is how destructors are going to get invoked so let us see a particular example here I have a base class this is the constructor for the base and this is the destructor for the base here is a derived class this is the constructor for the derived class and this is the destructor for the derived class what I am doing in the main program is I am instantiating an object of the derived class. So, as you would expect what is the output that I would see an object of the derived class is also an object of the base class. So, the base constructor is going to get invoked first it will print constructor base then the body of the constructor for the derived class is going to get invoked. So, it will print constructor savings and then when I am returning when this program ends and I am executing return 0 and terminating this program then this object has to be destroyed. But now because this object is of a derived class the order in which the destructors are going to get called is that the destructor of the derived class will first get called. So, I will first see destructor savings and then the destructor of the base class is going to get called. So, I will see destructor base. So, you see that when an object is instantiated of a derived class the constructor for that derived class is called, but that immediately first calls the constructor of the base class and then it executes the other statements in the constructor of the derived class. But when the object is destroyed the destructor of the derived class is first called and then the destructor of the base class is called. So, we have just seen that when I have a derived class it does not really inherit the constructors and destructors from the base class. For all other member functions as long as the access control specifications permit they are derived from the base class. Now there is another member function of the base class which is also not inherited by a derived class and that is the assignment operator method. Now you would recall from your previous lectures that when I define a class I could also define this assignment operator for the class and this specifies exactly what happens when an object of class base is assigned to another object of class base. Exactly this is the sequence of instructions that gets executed we have already studied this in an earlier lecture I am not going to repeat those. What I am going to point out however that this is the method for the assignment operator and in this particular case this is the base constructor for this base class and now let us say I have a derived class clearly the derived class does not inherit the constructor from the base class neither does it inherit the destructor from the base class it inherits the data members it inherits the other methods defined within the base class as long as the access control specifications permit but does it inherit this assignment operator and the answer to that is no it does not inherit the assignment operator. So here is the constructor for the derived class it does not inherit it from the base class it does not inherit the assignment operator also from the base class but of course every class has a default assignment operator if you do not provide one that can be used to make an assignment of an object of class savings to another object of class savings. So let us see what happens in this little main program here where we have some assignments. So here I have first instantiated an object B1 of class base initialized the constructor with this argument 10 and then I have declared two objects as one and S2 of the class savings and provided arguments to the constructor for this derived class in both of these cases and now I have this assignment operator which says B1 is assigned S1. Now if you recall from your earlier lectures where we talked about the assignment operator this B1 is assigned S1 what is really done is you invoke this method operator equal to on the object B1 and provide S1 as argument to it and here is the definition of operator equal to for the object B1 which is of class base note that this operator equal to expects its argument to be of class base but S1 is of class savings. Now this is not a problem because the class savings is derived from the class base so an object of class savings can also be treated as an object of class base and so this is perfectly fine and this method is going to get executed which means S1.id this is the argument that is passed the argument that is passed is S1. So S1.id will get copied to B1.id you will see the statement base class operator being printed and then the operator equal to method will return but what happens with this statement when I am trying to assign B1 to S2. Once again if you recall how assignments are made how operator equal to is used this will try to invoke the operator equal to method for the object S2 with the argument B1. Now here we have not specified the operator equal to method for the savings class it does not inherit the operator equal to method from the base class. So it is only going to use the default operator equal to method which is provided with every class and this default operator equal to the default assignment operator if you recall is just going to copy the data members of this class from the right hand side to the left hand side. So in this particular case it is going to try to copy the data member age of the object B1 and assign it to the data member age of the object S2 but hey see here there is no data member for the object B1 because B1 is an object of class base and an object of the base class cannot be treated like an object of the derived class although an object of the derived class can be treated like an object of the base class. So there is a problem here the default assignment operator of the savings class wants to copy the data member age from B1 to S2 but B1 does not have a data member age and so this is going to lead to a compilation problem. So there will be a compilation error and we will not be able to compile this program. Note that this is happening because the operator equal to method from the base class was not inherited here if it was inherited we could have made this assignment because then I would know that I need to just copy B1.id to S2.id. However because the assignment operator is not inherited I cannot do this. So in summary in this lecture we saw how member functions of a base class can be derived can be redefined in a derived class we saw how to access methods of a base class from a derived class and we studied about constructors, destructors and assignment operators and how they are sequenced when we talk about derived classes and base classes. Thank you for your attention.