Unit 2 Overloading and Inheritance Operator overloading • C++ incorporates the option to use standard operators to perform operations with classes in addition to with fundamental types. For example: int a, b, c; a = b + c; • Nevertheless, it is not so obvious that we could perform an operation similar to the following one: struct { string product; float price; } a, b, c; a = b + c; Vector addition Write a C++ program for vector addition Program for vector addition Cont… What if instead of airPlane.addVectors(propellor,wind); We wrote (in main) airPlane = propellor + wind; Compile time errors • Multiple markers at this line • - 'Vector' is not derived from 'const std::basic_string<_CharT, Traits, _Alloc>' • - mismatched types 'const _CharT*' and 'Vector' • - candidates are: • - no match for 'operator+' (operand types are 'Vector' and 'Vector') • - 'Vector' is not derived from 'const std::reverse_iterator<_Iterator>' Need of overloading? • The user can understand the operator notation more easily as compared to a function call because it is closer to the real-life implementation. • Associating a set of meaningful operators, manipulation of an ADT can be done in a conventional and simpler form. Original meaning of operators never get lost, when it’s overloaded Types of operator • Assignment(=) • Unary (+5 or -x) • Binary(a+b or 4-6 etc) • Homework Data X,Y; – Copy the data member of object X into Y by overloading the assignment operator(without using copy constructor), cout<<Y.getData(); Overloading using Binary operator • Example: Vector addition • airPlane = propellor + wind; //it’s like, //airPlane = propellor.operator+(wind) • • #include <iostream> using namespace std; • • • • class Vector { private: int ax; int ay; • • • • • public: Vector() { ax = 0; ay = 0; } • • • • Vector(int ax, int ay) { this->ax = ax; this->ay = ay; } • • int getAx() {return ax;} int getAy() {return ay;} • • • • void addVectors(Vector propellor, Vector wind) { this->ax = propellor.getAx() + wind.getAx(); this->ay = propellor.getAy() + wind.getAy(); } • • Vector operator+ (Vector); }; • • • • • • Vector Vector::operator+ (Vector param) { Vector temp; temp.ax = ax + param.ax; temp.ay = ay + param.ay; return (temp); } • • • int main(int argc, char **argv) { Vector propellor(3, 4), wind(7, 5), airPlane; cout << airPlane.getAx() << endl; • airPlane = propellor + wind;//it's like, propellor.operator+(wind) • • • cout << airPlane.getAx()<<endl;//prints 10 cout << airPlane.getAy(); //prints 9 } Overloading using Unary operator • Modification to previous program is to add one more long data and negate it as well. Friend classes • We can define a class as friend of another one, granting that first class access to the protected and private members of the second one. • Example- Create a class twoInt (only only getter setter methods should be there). Make class Sum (friend of twoInt) with method int addXY(twoInt ob); and in main call this method to print the addition of two integers(x,y)which are present in twoInt. • If class X is friend of class Y, it means X can have access to members of class Y but reverse is not true. • E.g. class Y{ int j; public: friend class X; //X is friend of Y }; • To make class Y friend of class X we have to write • class X{ int k; public: friend class Y; //Y is friend of X }; • Another property of friendships is that they are not transitive: The friend of a friend is not considered to be a friend unless explicitly specified. Friend function • In principle, private and protected members of a class cannot be accessed from outside the same class in which they are declared. However, this rule does not affect friends. • Create two classes alpha and beta with one constructor and one integer in each without any member function. In main print the addition of those integers. • Friend class or function declarations can be placed anywhere in the class; it doesn’t matter whether it goes in the public or the private section. Operator overloading using friends • Friend functions can be used in the place of member functions for overloading a binary operator. • Friend function requires two arguments to be explicitly passed; while in case of member function, it requires only one. Example • Create a class Person with Fname and Lname. Create 3 objects p1,p2,p3. With the use of friend overloading, in main call p3=p1+p2; which should create new person p3, with Lname of p1 and Fname of p2. E.g. p1=“Vaibhav Lokhande” p2=“Priyanka Chopra” then p3=“Priyanka Lokhande” //It means p1 and p2 got married. Why overloading using friends??? • In some cases it’s necessary to use friend function rather than member function. E.g. In the previous wedding example, what if the operator overloading is done without using friend function??? What are the advantages and disadvantages? • Advantage (without using friends)- Only one parameter is required for overloading function. Disadvantage(without using friends) Case-1 What if the line 61 is replaced with p3 = “Lokhande" + p2; //got married Case-2 What if the line 61 is replaced with p3 = p2 + " Lokhande "; Will program run? • In both the cases, program will give compile time errors. -The left hand operand that is accountable for invoking the member function should be an object of the same class. -Both the operands (on RHS) should be object of same class. In both the cases, one is object of Person class and other is string type(built-indata type or primitive type). If we want to make case-1 to run successfully, what to do??? • Use operator overloading with friends. Giving direct access to set private members (via friend) makes program run faster, because setting via setters is kind of indirection Homework • Write a program for case-2!!! • What if line 70 in previous slide is changed with p3 = p1 + 2; (Re-write a program to sort out the errors, so that it will print Vaibhav 2) Rules for operator overloading • New operators can’t be produced, though you are using valid operators (e.g. new+delete ) • In binary operator overloading without using friends, left hand operand must be of userdefined type (object of class) • 2 pgms- same functionality of two funs..one is member n other is non-member…which one will be called? • Without making friend fun,…try to overload + with non-member…try to access private data……ask for the error. What is the output??? • Compile time error……accessing private data members in non-member function without making it as friend. What will be the error??? Multiple markers at this line - ambiguous overload for 'operator+' (operand types are 'Person' and 'Person') Is it possible to make main a friend of any class??? • It is possible but it will not have any effect. • Means you will not be able to access the private members (directly or through object of that class). Some rules for operator overloading • The basic meaning of an operator can’t be changed. • Overloaded operators can’t be overridden. • Member functions can be used to overload certain operators while friend functions can’t be. • The left-hand operand must be an object of relevant class, in case of binary operators overloaded through member function. • Overloaded operators must be a non-static member function or a global function (should be friend of that class). A global function must take at least one argument that is of class or enumerated type or that is reference to a class or enumerated type. • Overloaded operators (function) can’t have default arguments. • . .* :: overloaded. ?; these operators can’t be • = () [] -> these operators can’t be used with friend keyword. Type conversions • • • • • • • int s; float k = 5.5; s = k; cout<<s; //output is 5 s= 9; k = s; cout<<k; //output is 9 • This is an example of automatic/implicit type conversion, since built in data-types are used. • Conversion from basic to Class type • Conversion from class to basic type • Conversion from class to class type Conversion from basic to Class type • Line 21 is like implicit overloading of = operator, which in turn calls parameterized constructor. What will be the output??? • Compile time error at line 16Multiple markers at this line - no match for 'operator=' (operand types are 'Time‘ and 'int') - candidate is: If we add parameterized constructor, then problem will be solved. But how to solve the above problem, without using parameterized constructor?? Overload operator = That’s it!!! Homework!!! • Make operator= an friend function. Ans- It is not possible, since friend function will not be able to overload = operator. Conversion from class to basic type (Using casting operator function) What will be the output??? • Compile time error-'int Vector::x' is private 'float Vector::y' is private • This is another way to convert class to float float g = float(v); • The casting operator function must satisfy -It should be class member -No return type and no arguments Conversion from class to class type Output will be 9 15.9 • Converting Vector to Vect i.e. copying x to x1 and y to y1. • Such a conversion from Vector to Vect class takes place by constructor or conversion function. • Conversion function has prototype operator typename() { } where typename is user-defined type (like class) or built-in-type (like int). Homework!!! • Use constructor method to convert Vector to Vect and not conversion function. Inheritance • Definition- Receive/Obtain something from someone. • E.g. Square IS-A Polygon, Child inherits some properties from Mom and Mom IS-A Person therefore Child IS-A Person….. Polygon- A plane shape with 2 dimensions viz length and height (with straight lines). Apart from being Polygon, square has 3 unique features Triangle • Square IS-A polygon as well as triangle IS-A polygon • Polygon is called as Base class and square and triangle are called as Derived classes. • Create a class Polygon with 2 attributes as length and width with POJO. Now create a class Rectangle as derived from Polygon. Rectangle will have function to calculate area of Rectangle. Set length = 5 and width = 7 using Rectangle object and display the area. • Create a class Polygon with 2 attributes as length and width with POJO. Create a class Rectangle which extends Polygon. Now create a class Square as derived from Rectangle. Square will have function to calculate area of square. Set length = 5 and width = 7 using Square object and display the area. Note: Protected members are not only accessible to immediate derived class but to any level of derived classes. • To define a derived class, use syntax class derived-class: access-specifier base-class • The access-specifier is required to give access to the next class, who is going 2 derive form derived class. • There are 3 access specifiers: public, protected and private. • Public: When deriving a class from a public base class, public members of the base class become public members of the derived class and protected members of the base class become protected members of the derived class. • A base class's private members are never accessible directly from a derived class, but can be accessed through calls to the public and protected members of the base class. • Protected : When deriving from a protected base class, public and protected members of the base class become protected members of the derived class. • Private : When deriving from a private base class, public and protected members of the base class become private members of the derived class. What will be the output??? Output will be 100 • In line 11, Polygon gives protected access to Rectangle class….it means that, Public members of Polygon will be public to the classes which will derive from Rectangle and protected members of Polygon will be protected to the classes which will derive from Rectangle. What will be the output??? • The code will not compile because using namespace std; is missing. In exam this kind of tricks examiners usually don’t do….but it was to test the reading power of one’s eyes….!!! Conclusion- Apart from active listener you should be active reader….thanks to Soft Skill… What will be the output??? • Compile time error at line 27 and 30, since class Rectangle gets private derived access from Polygon. • Due to that, protected members of Polygon (length, height) will become private in Rectangle. • At line 27 and 30 in class Square, we are trying to access these private variables, which gives compile time error. Access Control and Inheritance • A derived class can access all the non-private members of its base class. What will be the output(WWBTO)??? Base Derived • Although the constructors and destructors of the base class are not inherited themselves, default constructor and destructor of base class are always called when a new object of a derived class is created or destroyed. WWBTO??? BaseC Derived BaseD WWBTO??? BaseC Derived Types of Inheritance • Single- one derived class inherits from one base classs • Multiple- one derived class inherits from multiple base classes • Hierarchical- multiple subclasses inherits from one base class • Multilevel- here subclass acts as a base class for other classes • Hybrid- combination of other (previous 4) types of inheritance Homework- Create your own examples of any 2 types of inheritance and implement it. Multiple inheritance • In C++ it is perfectly possible that a class inherits members from more than one class. This is done by simply separating the different base classes with commas in the derived class declaration. • E.g. class CRectangle: public CPolygon, public COutput; • Output: 20 10 WWBTO??? Compile time error at line 27,30 • If while defining derived class, accessspecifier is not specified then by default it’s private. • A class can always access its own members in spite of any access specifier. • If the base class has no default constructor or you want that an overloaded constructor is called when a new derived object is created, you can specify it in each constructor definition of the derived class: derived_constructor_name (parameters) : base_constructor_name (parameters) {...} Lets see an example…. Output Polymorphism • Before getting into this section, it is recommended that you have a proper understanding of pointers and class inheritance. • If any of the following statements seem strange to you, you should review the indicated sections: • Polymorphism is a generic term that means 'many shapes'. • In C++ the simplest form of Polymorphism is overloading of functions, for instance several functions called SortArray( arraytype ) where sortarray might be an array of ints, or doubles. • Typically, polymorphism occurs when there is a hierarchy of classes and they are related by inheritance. • C++ polymorphism means that a call to a member function will cause a different function to be executed depending on the type of object that invokes the function. • The most common use of polymorphism in OOP occurs when a parent class reference is used to refer to a child class object. • Ex- Class square and triangle are derived from class polygon. There is function called area in both child classes. Use set_values function in base class to initialize values of width and height. Use only one base class pointer to set_values for square then display the area. Now use same pointer to set values for triangle and display its area as well. Virtual members • A member of a class that can be redefined in its derived classes is known as a virtual member. • In order to declare a member of a class as virtual, we must precede its declaration with the keyword virtual. Virtual Functions • WWBTO??? • Polymorphism works on pointer of class type and not on which derived class’s address it holds. • What if, we remove show function from Base class??? WWBTO??? Compile-time error at line 33,37 • Since p is pointer to class Base, compiler will try to search show function in Base class. Show function is not available in Base class, so it will give an error. • Oh my God….how to make it work?!!!!! – Its virtual function • If both base and derived classes has same function, then using pointer of base class we can call derived class function. (make base class function vitrual) WWBTO??? WWBTO??? 20 10 0 WWBTO if we remove keyword virtual??? 0 0 0 • That is because instead of calling the corresponding area() function for each object (CRectangle::area(), CTriangle::area() and CPolygon::area(), resp), CPolygon::area() will be called in all cases since the calls are via a pointer whose type is CPolygon*. Abstract base classes • Abstract base classes are something very similar to our CPolygon class of our previous example. • The only difference is that in our previous example we have defined a valid area() function with a minimal functionality whereas in an abstract base classes we could leave that area() member function without implementation at all. • This is done by appending =0 (equal to zero) to the function declaration. • This type of function (area) is called a pure virtual function, and all classes that contain at least one pure virtual function are abstract base classes. WWBTO??? Compile-time error (line 29) • The main difference between an abstract base class and a regular polymorphic class is that because in abstract base classes at least one of its members lacks implementation we cannot create instances (objects) of it. • But a class that cannot instantiate objects is not totally useless. We can create pointers to it and take advantage of all its polymorphic abilities. • CPolygon includes a pure virtual function and therefore it's an abstract base class. However, pointers to this abstract base class can be used to point to objects of derived classes. • Pure virtual members can be called from the abstract base class. WWBTO??? 20 10 Homework!!! • What happens if we change line 29 to 32 by following two lines….. CPolygon * ppoly1 = new CRectangle; CPolygon * ppoly2 = new CTriangle; Will number of lines of code increase or decrease??? More @ virtual • By default, C++ matches a function call with the correct function definition at compile time. This is called static binding. • You can specify that the compiler match a function call with the correct function definition at run time; this is called dynamic binding. • You declare a function with the keyword virtual if you want the compiler to use dynamic binding for that specific function. • Homework- Distinguish between pointers and references in C++ static binding Output is Class A Why??? • At compile time, the compiler knows only that the argument of function g() will be a reference to an object derived from A, therefore function A::f() is called. How to print Class B as output??? • The virtual keyword indicates to the compiler that it should choose the appropriate definition of f() not by the type of reference, but by the type of object that the reference refers to. • A class that declares or inherits a virtual function is called a polymorphic class. WWBTO??? • Compile-time error at line 20 because trying to invoke parameterized function f which is not available. WWBTO??? Class A Class C Though at line 20 pa1 contains address of class B, class B don’t have function with prototype f(). Therefore it takes it from base class itself. Covariant • Ex- Class Derived inherits from class Base. Base class contains pure virtual function called clone(). Clone function’s work is to create object of the class dynamically where it’s defined. First create Derived class’s one object dynamically, like Derived* d = new Derived; Now using d create one clone and point d2( derived class pointer) to it. WWBTO??? Compile-time error at line 41 • invalid conversion from 'Base*' to 'Derived*‘ • Line 35 is equal to (Base *)new Derived; We are assigning Base pointer to Derived pointer, which is not possible. Then how to remove the error??? WWBTO??? • If, instead, the clone() method could tell the compiler "actually, I always return a Derived*" (i.e. it became virtual Derived* Derived::clone() we could do away with the upcast and the check, moving all this away from run-time and into compile-time: Derived* d = new Derived; Derived* d2 = d->clone(); This is the ideal solution; there is no run-time cost associated with it, and it's completely safe (homework—what is run-time cost, safety). Derived * clone() is covariant function, output is B_Clone • The return type of an overriding function must be identical to the function that it is overriding. • The C++ Standard allows one specific exception to this rule that could possibly come in handy to save some unnecessary casting. • In an overridden method that returns a pointer or a reference to a class, you are allowed to change the return type to a derived class instead. • What is covariant??? • Changing (variable) in such a way that interrelations with other variable remain unchanged. • Means, even if someone is changing….they are still compatible to each other. Covariant return type • In object-oriented programming, a covariant return type of a function is one that can be replaced/changed by a "narrower" type when the function is overridden in a subclass. • Derived class return type is said to be covariant. Constructor, Destructor and virtual destructor • WWBTO??? • Compile time error since constructors are private. WWBTO??? a b WWBTO??? a b ~a Destructor of class B is not called because of static binding. How to call it? Virtual destructor a b ~b ~a Note: While dealing with inheritance make destructors virtual. Binding • Conversion of variables or function names into machine language addresses. • Early/static binding- A direct call to function is considered as early binding. At compile time, compiler is able to find address of function or variable. Example Late/dyanmic binding • In some cases, we come to know which function to call at runtime, it’s late binding. • Early binding is fast, efficient and less complex. • Late binding is slow, complex but more flexible compared to early binding. Container classes • A container is a holder object that stores a collection of other objects (its elements). • They are implemented as class templates, which allows a great flexibility in the types supported as elements. • The container manages the storage space for its elements and provides member functions to access them, either directly or through iterators. • E.g. dynamic arrays (vector), queues (queue), stacks (stack), heaps (priority_queue), linked lists (list), trees (set), associative arrays (map)... To know more…. • http://www.google.co.in/url?sa=t&rct=j&q=& esrc=s&source=web&cd=3&cad=rja&ved=0CD 0QFjAC&url=http%3A%2F%2Fwww.cs.colorad o.edu%2F~main%2Fsupplements%2Fchapt03. ppt&ei=1-vdUradM4IrAff9IDICQ&usg=AFQjCNFltjHNKDvbOIsoKE7l Oj0YDX_Jeg&sig2=qPSy4ak5BczeIW87qoRcVA Static class • Class that only has static members Ambiguity in multiple inheritance • The ambiguity simply means the state when the compiler confused. • So call to ambiguous members will result in compile-time error. • http://publib.boulder.ibm.com/infocenter/lnx pcomp/v8v101/index.jsp?topic=%2Fcom.ibm. xlcpp8l.doc%2Flanguage%2Fref%2Fcplr138.ht m • In multiple inheritance, there may be possibility that a class may inherit member functions with same name from two or more base classes and the derived class may not have functions with same name as those of its base classes. If the object of the derived class need to access one of the same named member function of the base classes then it result in ambiguity as it is not clear to the compiler which base’s class member function should be invoked. Lets code this scenario…… WWBTO??? Solution of ambiguity in multiple inheritance • The output to last program is a_abc • The ambiguity can be resolved by using the scope resolution operator to specify the class in which the member function lies. Virtual base classes • Virtual base classes offer a way to save space and avoid ambiguities in class hierarchies that use multiple inheritance. • The following figure shows the conceptual memory layout. • Note that there are two Queue subobjects in the LunchCashierQueue object. • Declare Queue a virtual base class will ensures that only one copy of the subobject Queue is included WWBTO??? Compile time error Multiple markers at this line - no matching function for 'PoweredDevice::PoweredDevice()‘ call to When we called parameterized constructor, in derived class, we are not mentioning which base class constructor to be called. So by default, it will call default constructor…which is not present in base class…..so it will give an error. • Check slide # 115-117 Correction to last program “diamond problem” in multiple inheritance • If you were to create a Copier class object, by default you would end up with two copies of the PoweredDevice class — one from Printer, and one from Scanner. WWBTO??? • How not to print PoweredDevice: 3 twice??? • How to bring the following output??? While deriving base class, make it virtual to immediate derived classes • To share a base class, simply insert the “virtual” keyword in the inheritance list of the derived class. This creates what is called a virtual base class, which means there is only one base object that is shared. • Here is the an example (without constructors for simplicity) showing how to use to virtual keyword to create a shared base class: • Now, when you create a Copier class, you will get only one copy of PoweredDevice that will be shared by both Scanner and Printer. • Who is responsible for creating PoweredDevice object? – The Copier constructor is responsible for creating PoweredDevice. Consequently, this is one time when Copier is allowed to call a non-immediateparent constructor directly. • If a class inherits one or more classes that have virtual parents, the most derived class is responsible for constructing the virtual base class. • Note that this is true even in a single inheritance case: if Copier was singly inherited from Printer, and Printer was virtually inherited from PoweredDevice, Copier is still responsible for creating PoweredDevice.