240 likes | 407 Views
Inheritance and Polymorphism: Part 2. BCA Sem III K.I.R.A.S. What is the need for Inheritance?. There are basically 2 reasons for the introduction of the concept of inheritance: 1) Reusability (the new derived classes can use the features of base classes )
E N D
Inheritance and Polymorphism: Part 2 BCA Sem III K.I.R.A.S
What is the need for Inheritance? • There are basically 2 reasons for the introduction of the concept of inheritance: 1) Reusability (the new derived classes can use the features of base classes ) 2) Transitive nature of inheritance : it can be passed on further
Visibility modes • It can be public, protected or private .The private data in base class cannot be inherited • Public: In public mode the public members of the base class become public in derived class and protected members become protected in the derived class • Private: In private mode the public members of the base class become private in derived class and protected members become private in the derived class • Protected: In protected mode the public members of the base class become protected in derived class and protected members become protected in the derived class • In case we write something like: Class derived :base //private derivation mode by default { // }; When we say that the members of a class are inheritable , it means the derived class can access them directly. However the derived class only have access to the non-private members of the base class . Although the private members of the base class cannot be accessed directly, yet the objects of the derived class are able to access them through the non-private inherited members
Public visibility mode Class marks Class student private private Class student { private: int x; void getdata(); public: int y; void putdata(); protected: int z; void check(); }; Class marks :public student { private: int a; void readdata(); public: int b; void writedata(); protected: int c; void checkvalue(); }; x getdata() a readdata() Public public y putdata() y putdata() b writedata() Protected protected c checkvalue() z check() z check() Inherited from student class
Private visibility mode Class marks Class student Private private a readdata() class student {//same }; class marks: private student {//same }; x getdata() y putdata() z check() public y putdata() Public b writedata() Protected z Protected check() c checkvalue() Inherited from student class
Protected visibility mode Class marks Class student Private private a readdata() class student {//same }; class marks: protected student {//same }; x getdata() Public public b writedata() y putdata() Protected Protected z c checkvalue() check() putdata() y z check() Inherited from student class
What is Run Time Polymorphism • Run time polymorphism (implemented in C++ with virtual functions) is the third essential feature of an object oriented programming language, after data abstraction and inheritance. • C++ virtual function is a member function of a class, whose functionality can be over-ridden in its derived classes. C++ virtual function is, * A member function of a class * Declared with virtual keyword * Usually has a different functionality in the derived class * A function call is resolved at run-time C++ virtual functions are used to achieve run time polymorphism. To declare a virtual function virtual keyword is put at the start of normal function declaration. Requirements for implementing virtual function- * Base Class Pointer * Inheritance * Method Overriding. It is a functions whose behavior can be overidden with an inherited class by a function of same signature. It is an important part of OOPS and Polymorphism.
What is a virtual function ? • A virtual function is a member function that is declared within the base class and redefined by a derived class. When a class containing a virtual function is inherited ,the derived class redefines the virtual function to fit its needs. • A virtual function is a member function you may redefine for other derived classes, and can ensure that the compiler will call the redefined virtual function for an object of the corresponding derived class, even if you call that function with a pointer or reference to a base class of the object. • You declare a function with the keyword virtual if you want the compiler to use dynamic binding for that specific function. • A class that declares or inherits a virtual function is called a polymorphic class • A virtual function must be one of the following: 1) Defined 2) Declared pure
Pure virtual functions and abstract classes • A pure virtual function is a virtual function that has no defination within the base class and it acts as a placeholder that is meant to be redefined by each derived class. When we add a pure virtual function to a class we actually mean to say that “ it is up to the derived class to implement this function “ • Pure virtual functions are also called “do-nothing “ functions in C++ because these functions are defined with a “null” body (they have no defination) • The syntax is : virtual return-type function-name(parameter list)=0; When a virtual function is made pure, any derived class must provide its own defination. If the derived class fails to override the pure virtual function a compile time error will result
Pure virtual functions and abstract classes • You can recognize a pure virtual function because it uses the virtual keyword and is followed by = 0. If anyone tries to make an object of an abstract class, the compiler prevents them (error ). This is a tool that allows you to enforce a particular design. • A class that contains at least one pure virtual function is said to be abstract class. Because an abstract class contains one or more functions for which there is no defination (pure virtual function ) , no objects for that class may be created.. Instead , an abstract class constitutes an incomplete type that is used as a foundation for derived classes • Abstract classes act as expressions of general concepts from which more specific classes can be derived. You cannot create an object of an abstract class type; however, you can use pointers and references to abstract class types. • A class that contains at least one pure virtual function is considered an abstract class. Classes derived from the abstract class must implement the pure virtual function or they, too, are abstract classes. • Creating a pure virtual function allows you to put a member function in an interface without being forced to provide a possibly meaningless body of code for that member function. At the same time, a pure virtual function forces inherited classes to provide a definition for it.
Pure virtual functions and abstract classes class person { virtual void print () = 0; }; • In the above example print() is a “dummy” function ,that means now person is an abstract class and cannot be instantiated (u cannot create an object of person class) The intention of person class is to provide a common interface for all the classes derived from it. The only reason to establish the common interface is so it can be expressed differently for each different subtype. It creates a basic form that determines what’s in common with all of the derived classes – nothing else. Person Virtual void print() Secretary void print() Teacher Int calculate() void print() Student Void enter() void print()
Destructors and Virtual Destructors • The constructor has the special job of putting an object together piece-by-piece, first by calling the base constructor, then the more derived constructors in order of inheritance (it must also call member-object constructors along the way). Similarly, the destructor has a special job: it must disassemble an object that may belong to a hierarchy of classes. To do this, the compiler generates code that calls all the destructors, but in the reverse order that they are called by the constructor. That is, the destructor starts at the most-derived class and works its way to the base class destructor . The proper hierarchy of constructor and destructor calls is automatically generated by the compiler • When an object is created with instantiating the derived class like [baseclass* bclass =new derivedclass() ] when you delete the base class pointer it calls the derived class destructor also so it leaves no chance for memory leak. If we do not declare the base class destructor as virtual ,only the base class destructor would be called when we say (delete bclass)
Virtual Base class • Consider a situation where 3 kinds of inheritance are involved: multilevel, hierarchical and multilevel student internalexams externalmarks marks
Virtual Base class • In this case the marks class has 2 direct base classes namely internalexams and externalexams ,which themselves have a common base class :student. The class marks inherits the traits of student class via two separate paths: first from internalmarks and second from externalmarks . Student is called the indirect base class. This means that marks class will have duplicate sets of the members inherited from “student “ class . This introduces ambiguity and must be avoided . The duplication of inherited members due to these multiple paths can be avoided by making the common base class as virtual class .i.e: class student { }; class internalmarks: public virtual student { }; class externalmarks: virtual public student { }; Class marks: public internalmarks, public exernalmarks {//only one copy of student will be inherited };
Virtual Destructor • The problem occurs when you want to delete a pointer of this type for an object that has been created on the heap with new. If the pointer is to the base class, the compiler can only know to call the base-class version of the destructor during delete. Forgetting to make a destructor virtual in a base class is a bug because it often doesn’t directly affect the behavior of your program, but it can quietly introduce a memory leak. Without a virtual destructor the proper destructor may not becalled
Why are there no virtual constructors? • Declaring something virtual in C++ means that it can be overridden by a sub-class of the current class, however the constructor is called when the object is created, at that time you can not be creating a sub-class of the class you must be creating the class so there would never be any need to declare a constructor virtual • Basically the virtual table will be constructed inside the constructor at the compilation time, this is table will contain the information about the all virtual functions present in side the class. A virtual table is nothing but an array of pointers to the virtual functions. The entries in the virtual table are changed at run time to point to the correct function. A constructor can not be virtual because at the time when constructor is invoked the virtual table would not be available in the memory .hence we can not have virtual constructor, (this is first time when we are invoking the constructor), Vtable is unique for the class
Why are there no virtual constructors? • The reason is that a virtual function is a function whose behavior depends on the type of the object that it's called for. A virtual call is a mechanism to get work done given partial information. In particular, "virtual" allows us to call a function knowing only an interfaces and not the exact type of the object. To create an object you need complete information. In particular, you need to know the exact type of what you want to create. Consequently, a "call to a constructor" cannot be virtual. • A virtual function is a function whose behavior depends on the type of the object that it's called for. Because constructors don't act on objects, but instead create them, a virtual constructor is not needed. A virtual call is a mechanism to get work done given partial information. In particular, "virtual" allows us to call a function knowing only an interfaces and not the exact type of the object. To create an object you need complete information. In particular, you need to know the exact type of what you want to create.
What is composition? • You simply create objects of your existing class inside the new class. This is called composition because the new class is composed of objects of existing classes. • Composition allows software to be developed by assembling existing components rather than creating new ones. Composition defines the process of putting an object of one class inside another class as data member . It models the “has-a” relationship.. Composition is the relationship between a class and its constituent parts. Example of “has –a” kind of relationship: • A university has an affiliated college We have 2 classes –university and affiliated college , making use of the object of affiliated college inside university class is going to model composition An automobile has an engine A human being has a heart
Composition vs. Inheritance • Inheritance and composition are the two most common mechanisms for software reuse. However, there exist some differences between the two • Inheritance is used to model “Is a kind of “ relationship whereas composition is used to model “has a kind of “ relationship. • A human being “has a” heart , we cannot say that a human being “is a” heart • Inheritance:- Two class can exhibits an IS_A relationship Composition:- This concept comes under containment (in which one (outer) object holds another (Inner) object). This shows the HAS_A relationship. In this type of containment the outer object controls the life time of the inner objects. e.g (outer)[Bank] HAS_A [Account](inner).
Aggregation vs. Composition • Composition and Aggregation are basically whole/part relationship. • Composition: When the lifetime of the part is dependent on or controlled by the whole, the relationship between the whole and part is Composition. Which simply means that the part is no more existing when the whole is destroyed. • example : car and engine.Aggregation : When the lifetime of the part is not dependent on or not controlled by the whole, the relationship between the whole and part is Aggregation. which simply means that the part continues to exist when the whole is destroyed. example : car and stereo • The only difference between composition and aggregation is lifetime. With composition, if object “a” is associated with objects b and c, and object a is destroyed, objects b and c are destroyed too. With aggregation b and c could live if a was destroyed.
Aggregation vs. Composition • Aggregation differs from ordinary composition in that it does not imply ownership. In composition, when the owning object is destroyed, so are the contained objects. In aggregation, this is not necessarily true. For example, a university owns affiliated colleges, and each affiliated college has a number of professors. If the university closes, the affiliated colleges will no longer exist, but the professors will continue to exist. Therefore, a University can be seen as a composition of affiliated colleges, whereas affiliated colleges have an aggregation of professors. • Aggregation - Without whole ,part can exist.Composition - Without whole, part can't exist • Aggregation or Composition depends up on life time of the child object.If the child object cannot exist beyond the lifetime of its parent then the relationship is composite (Strong relationship)If the child object can exist beyond the lifetime of its parent, then the relationship is aggregation
What is Delegation? • Delegation Is a way to make composition as powerful as inheritance . There are 2 objects involved , one receiving object delegates operations to its delegate • Delegation is an alternative approach, that is we can delegate some of the behavior of our new class to an object of the existing class without inheriting from it. (refer to example given in ch 14 of venugopal)
What is Run Time Type Identification (RTTI) • In polymorphic languages like C++ , there can be situations in which the type of the object is unknown at compile time,because the precise nature of that object is not known till the program is executed. Since the base class pointer may be used to point to the objects of base class or the objects of derived classes, it is not always possible to know in advance what type of object will be pointed to by the base class pointer at a given moment in time. This determination can be done at run time using RTTI • In order to obtain an object’s type use typeid(object) here object will be the object whose type u will be obtaining u can use dynamic_cast operator also to get information of object at run time
dynamic_cast dynamic_cast performs a run time cast that verifies the validity of a cast. If the cast is invalid at the time when dynamic_cast is executed ,then the cast fails Syntax: dynamic_cast<target type>(expr) Target type is specifies the target type of the cast and expr is expression being cast into the new type Class base { public: virtual void func(); }; Class derived: public base { }; Void main() { base *pb; derived *pd, d1; pb=&d1; If( pd=dynamic_cast<derived *>(pb) cout<<“type derived”; }