1 / 53

Chapter 5 Inheritance

Chapter 5 Inheritance. Objectives. Introduction, effects, and benefits of inheritance Base class and derived class objects Base class and derived class pointers Function overriding Base class initialization The protected access specifier

kioshi
Télécharger la présentation

Chapter 5 Inheritance

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Chapter 5Inheritance

  2. Objectives • Introduction, effects, and benefits of inheritance • Base class and derived class objects • Base class and derived class pointers • Function overriding • Base class initialization • The protected access specifier • Deriving by different access specifiers: public, protected, and private • Different kinds of inheritance • Order of invocation of constructors and destructors

  3. Introduction • A class may be defined in such a way that it automatically includes member data and member functions of an existing class. • Additionally, member data and member functions may be defined in the new class also. This is called inheritance. • The existing class whose features are being inherited is known as the base class or parent class or super class. • The new class that is being defined by inheriting from the existing class is known as its derived class or child class or sub-class.

  4. Introduction • The syntax for derivation is as follows: • A pointer from the derived class to the base class diagrammatically depicts derivation. Figure: diagrammatic depiction of Inheritance A B

  5. Effects of Inheritance Inheritance affects the size and behaviour of derived class objects in two ways: • Obviously, an object of the derived class will contain all data members of the derived class. However, it will contain data members of the base class also. Thus, an object of the derived class will always be larger than an object of the base class. (The only exception to this is when neither the base class nor the derived class has data members. In that case, objects of both the base class and the derived class occupy one byte each.) • Obviously, with respect to an object of the derived class, we can call the public member functions of the derived class in any global non-member function. • However, we can call the public member functions of the base class also.

  6. class A { int x; public: void setx( int =0); int getx() ; }; class B : public A { int y; void sety( int =0); int gety() ; }; void main() { cout<<sizof(A)<<endl<<sizof(B)<<endl; B b1; b1.setx(3); b1.sety(5); cout<<b1.getx()<<“\t”<<b1.gety(); }

  7. Effects of Inheritance • An object of the derived class will contain the data members of the base class as well as the data members of the derived class. • Thus, the size of an object of the derived class will be equal to the sum of sizes of the data members of the base class plus the sum of the sizes of the data members of the derived class. • Inheritance implements an ‘is-a’ relationship where a derived class is a type of the base class. For example, an aircraft (derived class) is a type of vehicle(base class) • Where as containership implements ‘has-a’ relationship A class may contain an object of another class or a pointer to a data structure that contains a set of objects of another class. Such a class is known as a container class. Containership implements a ‘has-a’ relationship. For example , an aircraft has one engine or an array of engines.

  8. Effects of Inheritance • Another example can be that of a manager class and employee class. • For example, it may have a pointer to an array of employees that report to him. Derived class object is also a base class object. class employee { char *name; double basic; date doj; //………………….. }; class manager: public employee { employee *list; //………………….. };

  9. A derived class contains additional data and members and is thus a specialized definition of its base class. Therefore, the process of inheritance is also known as specialization. Benefits of Inheritance: In inheritance, the process of adding only the additional data members in the derived class has following implications: • The base class can have a generic common definition. • The data and functions that are common to more than one class can be put together in the base class, while only the special ones can be put in each of the derived classes. • Thus, inheritance is another feature of C++ that enables code reusability.

  10. Base Class and Derived Class Objects: An object of the derived class is not at all related to another simultaneously existing object of the base class. Figure: Accessing Members of the Base Class in the Derived Class: Only public members of base class can be accessed in the functions of derived class, however, private members of the base class cannot be accessed. Example: Suppose in the base class B::sety() function: x=y; // compiler reports error • C++ prevents us from accessing private members of the base class in member functions of the derived class to fully implement data security. • Inheritance is used to provide additional data and additional code to work upon the additional data in the derived class which would supplement the base class.

  11. Accessing Members of the Base Class in the Derived Class: Void B::sety(int q) { y=q; setx(y); }

  12. Inheritance is used to add facilities to an existing class without reprogramming it or recompiling it. Thus, it enables us to implement code reusability. • Friendship is not inherited. A class does not become a friend to a class to which its parent is a friend. (i.e., if parent is a friend to one class, then child class need not be friend for that class)

  13. Function Overriding • Member functions of the base class can be overridden in the derived class. • Defining a member function in the derived class in such a manner that its name and signature match those of a base class function is known as function overriding. • Function overriding results in two functions of the same name and same signature. One of them is in the base class. The other one is in the derived class.

  14. Function Overriding Example: class A { int x; public: void show() { cout<<“Class A function is called\n”; } }; class B : public A { public: void show() { cout<<“Class B function is called\n”; } };

  15. Function Overriding • Calling the overriding function with respect to an object of the derived class is shown in : • void main() • { • B B1; • B1.show(); • } • Output?

  16. Function Overriding • Whenever a function is called with respect to an object of a class, the compiler first searches for the function prototype in the same class. Only if this search fails, the compiler goes up the class hierarchy to look for the function prototype. • The overridden function of the base class will be called if it is called with respect to an object of the base class: • void main() • { • A A1; • A1.show(); • } • Output?

  17. Function Overriding • The overridden base class function can still be called with respect to an object of the derived class by using the scope resolution operator: • void main() • { • B B1; • B1.A::show(); • } • Output? • Function overriding is actually a form of function overloading. • The signatures of the overriding function and the overridden function are different from each other. • void show (A *const);// show () function of class A • void show (B *const); // show () function of class B

  18. Function Overriding • The overridden function can be called from the overriding function but the scope resolution operator is necessary to avoid infinite recursion. • void B::show() • { • A::show(); • //rest of B::show() • } • Function overriding becomes significant when the base class function being overridden is virtual.

  19. Base Class Initialization • A derived class object is composed of data members of the derived class as well as those of the base class. • Often these data members need to be initialized while creating an object of the derived class. • When an object of the derived class is created, the compiler implicitly and inevitably embeds a call to the base class constructor and then the derived class constructor with respect to the object. • Example: • B B1; • is converted to • B B1; //memory allocated for the object • B.A(); • B.B(); • Destructors are called in the reverse order. Explicitly calling the constructors and destructors, with respect to an existing object, is prohibited.

  20. Base Class Initialization Example: shows an unsuccessful initialization of base class members. class A { int x; public: A(const int=0); void setx( int =0); int getx() ; }; class B : public A { int y; public: B(const int=0); void sety( int =0); int gety() ; }; void main() { B B1(10); cout<<b1.getx()<<“\n”<<b1.gety(); } Output?

  21. Base Class Initialization • While creating an object of the derived class, we would like to pass a value explicitly to the base class constructor. The constructor of class B from (defined in previous example) should take not one but two parameters. • Hence, the derived class constructor should be modified to ensure successful initialization of the base class members Example: class B : public A { int y; public: B (constint=0, const in =0); void sety( int =0); intgety() ; }; B:: B (constinti, constint j):A(i) {y=j;}

  22. Base Class Initialization • An object of class B can be declared by passing two parameters to its constructor. • Example: • void main() • { • B B1(10,20); • cout<<b1.getx()<<“\n”<<b1.gety(); • } • Output ? • Any of the parameters passed to the derived class constructor can be passed to the base class constructor. • The statement B B1(10,20) • gets converted to • B B1; • B1.A(10); • B1.B(20);

  23. Base Class and Derived Class Pointers • A base class pointer can point at an object of the derived class without the need for typecasting. • Example: • class A • { • public: int x; • }; • class B: public A • { • public: int y; • }; void main() { A *Aptr; B B1; Aptr=&B1; Aptr->x=10; Aptr->y=20;// Error, y is not found in class A }

  24. Base Class and Derived Class Pointers • Derived class pointer cannot point at an object of the base class • Example: void main() { B *Bptr; A A1; Bptr=&A1;// Error, can’t convert from B* to A* Bptr->x=10; Bptr_>y=20; }

  25. Derived Class Pointers • Derived class pointer cannot point at an object of the base class. It is supposed to point to an object of derived (class B), since its type is B*. • But the derived class pointer, can access the members of both base (member x ) as well as derived class (member y) • A derived class pointer can be made to point at an object of the base class only forcibly by typecasting. • Example • void main() • { • B *Bptr; • A A1; • Bptr=(B*) &A1;//to make derived class pointer point at base class object • Bptr->x=10; • Bptr->y=20; • } • This can cause run-time errors. • Since derived class pointer is forcibly made to point to base class object, even if the memory is not allocated for derived class data members, the pointer can access the data from unallocated memory block. This is unsafe. • Explicit address manipulation like this is obviously dangerous.

  26. Base Class and Derived Class Pointers The member functions in previous example access private data members of their respective classes. class A { int x; public: void setx( int =0); }; class B : public A { int y; public: void sety( int =0); }; void main() { A *Aptr; B B1; Aptr= &B1; Aptr->setx(10); Aptr->sety(20);//error, sety() is not a member } Listing 5.10 shows a pointer in a base class member function pointing at the derived class invoking object.

  27. Base Class and Derived Class Pointers void main() { B *Bptr; A A1; Bptr= &A1;//error Aptr->setx(10); Aptr->sety(20); } • Following example shows a pointer in a base class member function pointing at the derived class invoking object. B1. setx(10); based on the concept of this pointer, the above statement is converted as: setx(&B1, 10);// addr of B1 is passed as pointer as a parameter to the function: void setx(A *const this, const int p) { this->x=p; } • i.e., this pointer points at B1.

  28. The Protected Access Specifier • Protected members are inaccessible to non-member functions. However, they are accessible to the member functions of their own class and to member functions of the derived classes. • Apart from the public and private access specifiers, there is a third access modifier in C++ known as protected.

  29. Deriving by Different Access Specifiers 1. Deriving by the Public Access Specifier Deriving by the public access specifier retains the access level of base class members. • Private members: Member functions of the derived class cannot access. Member functions of the subsequently derived classes cannot access them. Non-member functions cannot access them. • Protected members: Member functions of the derived class can access. Member functions of the subsequently derived classes can also access them. Non-member functions cannot access them. • Public members: Member functions of the derived class can access. Member functions of the subsequently derived classes can also access them. The non-member functions can also access them.

  30. Deriving by Different Access Specifiers Deriving by the Public Access Specifier • A base class pointer can point at an object of a derived class that has been derived by using the public access specifier. • The C++ compiler does not prevent a base class pointer from pointing at an object of the derived class if the public access specifier has been used to derive the class.

  31. Deriving by Different Access Specifiers 2. Deriving by the Protected Access Specifier Deriving by the protected access specifierreduces the access level of public base class members to protected while the access level of protected and private base class members remains unchanged. • Private members: Member functions of the derived class cannot access. Member functions of the subsequently derived classes cannot access them. Non-member functions cannot access them. • Protected members: Member functions of the derived class can access. Member functions of the subsequently derived classes can also access them. Non- member functions cannot access them. • Public members: Member functions of the derived class can access. Member functions of the subsequently derived classes can also access them. Non-member functions cannot access them.

  32. Deriving by Different Access Specifiers Deriving by the Protected Access Specifier • A base class pointer cannot point at an object of a derived class that has been derived by using the protected access specifier. • The C++ compiler prevents a base class pointer from pointing at an object of the derived class if the protected access specifier has been used to derive the class.

  33. Deriving by Different Access Specifiers 3. Deriving by the Private Access Specifier Deriving by the private access specifier reduces the access level of public and protected base class members to private while access level of private base class members remains unchanged. (See Listing 5.23). • Private members: Member functions of the derived class cannot access. Member functions of the subsequently derived classes cannot access them. Non-member functions cannot access them. • Protected members: Member functions of the derived class can access. Member functions of the subsequently derived classes cannot access them. Non-member functions cannot access them. • Public members: Member functions of the derived class can access. Member functions of the subsequently derived classes cannot access them. Non-member functions cannot access them.

  34. Deriving by Different Access Specifiers Deriving by the Private Access Specifier • A base class pointer cannot point at an object of a derived class that has been derived by using the private access specifier. • The C++ compiler prevents a base class pointer from pointing at an object of the derived class if the private access specifier has been used to derive the class. • The default access specifier for inheritance is private.

  35. Different Kinds of Inheritance Following are the different types of inheritances: • Single inheritance • Multiple inheritance • Hierarchical inheritance • Multilevel inheritance • Hybrid inheritance • Single inheritance • In single inheritance, a class inherits implementation from only one super class. For example, if class B inherits from class A, class B will acquire all the members declared in class A. A B

  36. Different Kinds of Inheritance Multiple Inheritance • In multiple inheritance, a class derives from more than one base class. For e.g., class D is derived from base classes B1, B2. • The general syntax for multiple inheritance is as follows: • In multiple inheritance, for each of the base classes, a different access specifier can be used. B1 B2 D

  37. Different Kinds of Inheritance Multiple Inheritance • An object of a class defined by multiple inheritance contains not only the data members defined in the derived class, but also the data members defined in all of the base classes. • Hence, the size of such an object is equal to the sum of the sizes of the data members of all the base classes plus the sum of the sizes of the data members of all of the derived classes. • With respect to such an object, it is possible to call the member functions of not only the derived class, but also the member functions of all the base classes.

  38. Different Kinds of Inheritance Ambiguities in Multiple Inheritance Multiple inheritance leads to a number of ambiguities, namely, identical members in more than one base class and diamond-shaped inheritance. • Identical members in more than one base class: • The first ambiguity arises if two or more of the base classes have a member of the same name. • This ambiguity can be resolved by using the scope resolution operator. • This ambiguity can also be resolved by overriding the multiple inherited base class member. • Overridden members can be called by scope resolution operator.

  39. Different Kinds of Inheritance • Identical members in more than one base class: class A { public: void show() { c out<<“ Display A\n” ; } }; class B { public: void show() { c out<<“ Display B\n” ; } }; class C: public A, public B { } void main() { C C1; C1.show();// Ambiguity }

  40. Different Kinds of Inheritance • Identical members in more than one base class: class C: public A, public B { } void main() { C C1; C1.A::show(); //ok C1.B::show();//ok } OR class C: public A, public B { public: void show() { cout<<“display C\n”; } //override both of inherited functions } void main() { C C1; C1.show();// ok C1.A::show(); //ok C1.B::show(); //ok }

  41. Different Kinds of Inheritance Ambiguities in Multiple Inheritance • Diamond-shaped inheritance: • Ambiguities can also arise if two or more base classes in turn inherit from a common base class . • This is known as diamond-shaped inheritance. • The two previous solutions—using scope resolution operator and overriding—are applicable here also. • The third solution is declaring the top base class to be virtual.

  42. Virtual base class A B1 B2 D • Here all 3 kinds of inheritances, namely multilevel, multiple and hierarchical , are involved. • Here the class D has 2 direct base classes B1 and B2 which themselves have a common base class A. • The class D inherits the features of A via two separate paths, first via base class B1 and again via class B2. This means class D would have duplicate members inherited from A. This introduces ambiguity and should be avoided.

  43. Virtual base class • The duplication of inherited members due to these multiple paths can be avoided by making the common base class as virtual base class while declaring the intermediate base class • When a class is made virtual base class, C++ takes necessary care to see that only one copy of that class is inherited, regardless of how many inherited paths exist between the virtual base class and a derived class.

  44. class A { public: void show(); }; class B1: public A { }; class B2: public A { }; class D: public B1, public B2 { }; void main() { D D1; D1.show();//error }

  45. Virtual base class class A { public: void show(); }; class B1: virtual public A { }; class B2: public virtual A { }; class D: public B1, public B2 { }; Void main() { D D1; D1.show();//ok }

  46. Different Kinds of Inheritance Multi-level Inheritance: When a class inherits from a derived class, it is known as multi-level inheritance. • Multi-level inheritance can be extended to any level. • Multi-level inheritance is commonly used to implement successive refinement of a data type. For example, ‘Animal’ is a more generic class. ‘Mammal’ is a type of ‘Animal’. ‘Man’ is a type of ‘Mammal’ Hierarchical Inheritance: In hierarchical inheritance, a single class serves as a base class for more than one derived class. • Hierarchical inheritance is probably the best illustration of the virtues of code reusability. • The common features of two or more classes can be put together in a single base class that can then be inherited by those classes. The need to duplicate the common features in more than one class is, thus, eliminated.

  47. Different Kinds of Inheritance Multi-level Inheritance: Hierarchical Inheritance: A B C A C B D

  48. Different Kinds of Inheritance Hybrid Inheritance: Hybrid inheritance, as the name indicates, is simply a mixture of all the above kinds of inheritances. A B D C

  49. Order of Invocation of Constructors and Destructors Constructors are invoked in the following order: • Virtual base class constructors in the order of inheritance • Non-virtual base class constructors in the order of inheritance • Member objects’ constructors in the order of declaration • Derived class constructor Destructors are invoked in the reverse order.

  50. class A {public: A() { cout<<“Class A constructor called\n”; } ~A() { cout<<“Class A destructor called\n”; } }; class B: {public: B() { cout<<“Class B constructor called\n”; } ~B() { cout<<“Class B destructor called\n”; } }; class C: virtual public A {public: C() { cout<<“Class C constructor called\n”; } ~C() { cout<<“Class C destructor called\n”; } };

More Related