Inheritance in C++ Contd..2
Total Page:16
File Type:pdf, Size:1020Kb
Inheritance in C++ contd..2 [email protected] Reference Text: Chapter11, Big C++ Inheritance: Principle of Substitution • Manager is-a special type of employee. • Manager is also an Employee, It has all the properties any other employee has • A manager has every things that any other employee has, therefore it can substitute an employee Inheritance: Principle of Substitution • However when a manager is treated as any other employee, it can do the things which any other employee can do • In programming context, Manager object can substitute any Employee object, – however when manager object substitute employee object, you can only do operations which are available for employee objects Inheritance: Principle of Substitution • Example: Manager object substituting employee object- int main() { Manager m(“ABC”, 45000, “Marketing”); m.setBonus( 15000 ); m.getSalary(); //would give 60000 Employee e; e = m; //Now manager becomes like any other employee and its clone is identified as e //You can no more access Manager part of it- e.getBonus(); // is no more known, however e.getSalary(); //would give 45000 } • Objects of derived class are bigger, and can not be fitted in storage of base class. • Therefore assigning object of derived class to object of base class would slice away extra part of derived class • This phenomenon is known as object slicing Using base class pointers to access objects of derived class • Pointers of base class pointer can be used to point to objects of derived classes Employee* ep; ep = new Manager(“ABC”, 45000, “Marketing”); • Now ep points to full manager object, no slicing takes place, as object is externally stored. • However, while dereferencing, compiler allows only operations defined for type to which ep has been declared to point- ep->getSlalary(); //will be compiled ep->getDepartment(); //Will not compile Usages of principle of substitution • One of the important requirement in programming is we must be able to have collection of related objects; for example you have collection of employees, having mix of managers, engineers, staff members, or so • For this we may typically have array or vectors of various type of employees • Let us try storing some of objects of employee and managers classes in an array of Employee objects- may be principle of substitution can help here. Possible solution: would it output as expected? • Unfortunately, it will not work as expected. • Assigning object of derived class to object of base class would slice away extra part of derived class, so what basically this array contains for manager object is, Employee portion of Manager objects !! Let us try to have an array of dynamically created objects Would it work now, as expected? • Alternative let us not store objects in static array, let create an array of dynamic objects, and we store their address in the array. Unfortunately again No. • Compiler sees emp[1] is pointer to Employee object, even though it is pointing to Manager Object; and binds e[1]->getSalary to getSalary method of Employee class? • This is because binding is done at compile time, depending upon type declaration of pointer • Requires dynamic Binding ..? Dynamic Binding of method call • How do we do it ..? • In C++, we do it by making the method in base class as virtual • Virtual keyword indicates to the compiler that binding of this function as to be done at run time Virtual Function • Whenever a virtual function is called, the compiler determines the type of the implicit (this) parameter in the particular call at the run-time and appropriate function for that object is then called • For example, when getSalary() has been declared as virtual, then the call , emps[i]->getSalary(); would always call to the function belonging to the actual type to which emps[i] points • Only member functions can be virtual Virtual Function • A member function not tagged as virtual is statically bound. • That is, the type of implicit parameter, as it is known as compile time, is used to select appropriate function, and that function is always called. • Static binding is less complex and default in C++, therefore should use virtual function only when you have reason of having dynamic binding • Virtual function gives great deal of flexibility, you can loop through collection of different type of objects (though belong to a classes that inherits a common base class), and do some computation Now the client code below should work as expected, and would output: 125000 ? Would it output as expected? • Yes, if getSalary function is defined as virtual, then binding of e.getSalary in function show would be done at run-time • Passing by reference, also requires to be noted here, if you have Employee instead of Employee& as parameter type, then it would not work. • Then there is no possibility of dynamic binding as e itself is pure static employee object in the function. • Where as when you pass by reference, it refers to actual object which is associated when function is invoked, and that could be object of Employee class or any of its derived class. • Binding would be done at run time depending upon the type of actual object to which the e refers Method Overriding • When you redefine a function of base class in derived class, and base class function is virtual, then it is called as method overriding • Though in general redefinition of base class method is called method overriding, however, • in C++, redefining non-virtual function does not truly overriding as you do not get overridden behavior due to static binding • For example getSalary method of Manager class is overridden by redefining it and making virtual Employee class. • Virtual Property is inherited !! • If you define a function virtual in parent class, same function in derived class would also be virtual, irrespective of whether it is defined virtual or not in the derived class • Do chapter end exercises in Big C++ book Thanks.