Polymorphism and Virtual Functions. Topics Polymorphism Virtual Functions Pure Virtual Functions Abstract Base Classes Virtual Destructors V-Tables Run.

Slides:



Advertisements
Similar presentations
Constructors: Access Considerations DerivedClass::DerivedClass( int iR, float fVar) : BaseClass(fVar) { m_uiRating = uiR; } Alternatively DerivedClass::DerivedClass(
Advertisements

METHOD OVERRIDING 1.Sub class can override the methods defined by the super class. 2.Overridden Methods in the sub classes should have same name, same.
Chapter 1 OO using C++. Abstract Data Types Before we begin we should know how to accomplish the goal of the program We should know all the input and.
Inheritance and object compatibility Object type compatibility An instance of a subclass can be used instead of an instance of the superclass, but not.
Polymorphism From now on we will use g++!. Example (revisited) Goal: Graphics package Handle drawing of different shapes Maintain list of shapes.
V IRTUAL F UNCTIONS Chapter 10 Department of CSE, BUET 1.
Polymorphism, Virtual Methods and Abstract Classes.
Rossella Lau Lecture 8, DCO10105, Semester B, DCO10105 Object-Oriented Programming and Design  Lecture 8: Polymorphism & C++ pointer  Inheritance.
C++ Polymorphism Systems Programming. Systems Programming: Polymorphism 2   Polymorphism Examples   Relationships Among Objects in an Inheritance.
Shallow Versus Deep Copy and Pointers Shallow copy: when two or more pointers of the same types point to the same memory – They point to the same data.
Virtual Functions Fall 2008 Dr. David A. Gaitros
Computer Science and Software Engineering University of Wisconsin - Platteville 7. Inheritance and Polymorphism Yan Shi CS/SE 2630 Lecture Notes.
Chapter 13: Pointers, Classes, Virtual Functions, and Abstract Classes
1 Virtual Functions and Polymorphism Chapter What You Will Learn What is polymorphism? How to declare and use virtual functions for abstract classes.
Learners Support Publications Pointers, Virtual Functions and Polymorphism.
Cpt S 122 – Data Structures Polymorphism
1 Classes- Inheritance Multiple Inheritance It is possible to derive a new class from more than one base class. This is called Multiple Inheritance. Under.
Chapter 15 – Inheritance, Virtual Functions, and Polymorphism
Run-Time Type Identification Jim Fawcett CSE687 – Object Oriented Design Spring 2007.
Polymorphism. Introduction ‘one name multiple forms’ Implemented using overloaded functions and operators Early binding or static binding or static linking.
Polymorphism &Virtual Functions
Polymorphism &Virtual Functions 1. Polymorphism in C++ 2 types ▫Compile time polymorphism  Uses static or early binding  Example: Function and operator.
“is a”  Define a new class DerivedClass which extends BaseClass class BaseClass { // class contents } class DerivedClass : BaseClass { // class.
Static and Dynamic Behavior CMPS Power of OOP Derives from the ability of objects to change their behavior dynamically at run time. Static – refers.
1 Chapter 10: Data Abstraction and Object Orientation Aaron Bloomfield CS 415 Fall 2005.
Object Oriented Programming with C++/ Session 6 / 1 of 44 Multiple Inheritance and Polymorphism Session 6.
TCP1201 OOPDS Lecture 4 1. Learning Objectives  To understand upcasting & downcasting  To understand static polymorphism and dynamic polymorphism 
OOP and Dynamic Method Binding Chapter 9. Object Oriented Programming Skipping most of this chapter Focus on 9.4, Dynamic method binding – Polymorphism.
Polymorphism. 3 main programming mechanisms that constitute OOP: 1. Encapsulation 2. Inheritance 3. Polymorphism.
Polymorphism and Virtual Functions. Topics Polymorphism Virtual Functions Pure Virtual Functions Abstract Base Classes Virtual Destructors V-Tables Run.
CSCI-383 Object-Oriented Programming & Design Lecture 18.
CS212: Object Oriented Analysis and Design Lecture 17: Virtual Functions.
OOP using C Abstract data types How to accomplish the task??? Requirements Details Input, output, process Specify each task in terms of input.
Virtual FunctionstMyn1 Virtual Functions A virtual function is declared in a base class by using the keyword virtual. A function that you declare as virtual.
CS-1030 Dr. Mark L. Hornick 1 Basic C++ State the difference between a function/class declaration and a function/class definition. Explain the purpose.
CS212: Object Oriented Analysis and Design Lecture 16: Runtime Polymorphism.
Polymorphism, Virtual Methods and Interfaces Version 1.1.
Fall 2015CISC/CMPE320 - Prof. McLeod1 CISC/CMPE320 Assignment 3 is due Sunday, the 8 th at 7pm. Problems with assn 3? Discuss at your team meeting tonight.
Recap Introduction to Inheritance Inheritance in C++ IS-A Relationship Polymorphism in Inheritance Classes in Inheritance Visibility Rules Constructor.
Object Oriented Programming in C++ Chapter 7 Dynamic Binding.
Object Oriented Programming Elhanan Borenstein Lecture #7.
Polymorphism and Virtual Functions One name many shapes behaviour Unit - 07.
 2000 Prentice Hall, Inc. All rights reserved. Chapter 20 - Virtual Functions Outline 20.1Introduction 20.2Type Fields and switch Statements 20.3Virtual.
Class Inheritance Inheritance as an is-a relationship Public derive one class from another Protected access Initializer lists in constructor Upcasting.
J. Byrne Polymorphism what it means and when it is used.
CSC241 Object-Oriented Programming (OOP) Lecture No. 17.
OOP, Inheritance and Polymorphism Lecture 6. Object relations  Inheritance is ‘a kind of’, ‘a type of’ e.g. a revolver is a type of gun  Aggregation.
Computer Science Department Inheritance & Polymorphism.
1 Inheritance and Polymorphism Chapter Getting Started Continue the Cat Management example from previous presentation.
Polymorphism & Virtual Functions 1. Objectives 2  Polymorphism in C++  Pointers to derived classes  Important point on inheritance  Introduction to.
 Virtual Function Concepts: Abstract Classes & Pure Virtual Functions, Virtual Base classes, Friend functions, Static Functions, Assignment & copy initialization,
CSCI-383 Object-Oriented Programming & Design Lecture 17.
CPSC 252Inheritance II Page 1 Inheritance & Pointers Consider the following client code: const int MAXCLOCKS = 2; Clock* clockPtr[ MAXCLOCKS ]; clockPtr[0]
Inheritance Modern object-oriented (OO) programming languages provide 3 capabilities: encapsulation inheritance polymorphism which can improve the design,
Polymorphism, Virtual Methods and Abstract Classes
7. Inheritance and Polymorphism
Polymorphism &Virtual Functions
Class A { public : Int x; A()
Polymorphism.
CS212: Object Oriented Analysis and Design
Polymorphism & Virtual Functions
Polymorphism, Virtual Methods and Abstract Classes
Polymorphism Lec
Programming with ANSI C ++
Virtual Functions Department of CSE, BUET Chapter 10.
Today’s Objectives 10-Jul-2006 Announcements Quiz #3
VIRTUAL FUNCTIONS RITIKA SHARMA.
Chapter 11 Class Inheritance
Lecture 6: Polymorphism
Static Binding Static binding chooses the function in the class of the base class pointer, ignoring any versions in the class of the object actually.
Presentation transcript:

Polymorphism and Virtual Functions

Topics Polymorphism Virtual Functions Pure Virtual Functions Abstract Base Classes Virtual Destructors V-Tables Run Time Type Identification (RTTI) Dynamic Cast

Objectives At the completion of this module, students should be able to: Design classes that enable polymorphism * Properly use inheritance * Include virtual functions Correctly use polymorphism in a program * Store pointers to dynamically created objects in arrays of base class pointers Explain how V-Tables are used to make polymorphism work Explain why a virtual destructor is needed Safely access base class functions in a program, using rtti and dynamic casts.

Introduction : The Orchestra

Polymorphic Variables Consider the statement: Instrument* instr = new Brass(bugle, toot); The declared or static type of instr is Instrument* However, instr can potentially hold a pointer to a variable of a different type. In particular, it can hold the address of an object of any class derived from Instrument. The type of object actually pointed to is instrs dynamic type.

From Inheritance... Recall that you can store the address of a derived class object in a base class pointer. What happens if you use the base class pointer to invoke a function that exists in the base class, but has been over-ridden in the derived class?

Virtual Functions class Instrument { public: virtual void play ( ) const; void display ( ); protected: string name; }; the keyword virtual says that we can over-ride this function in a derived class. But, when we use a base class pointer to point to the object, and invoke the virtual function, the system will automatically find and execute the function defined in the derived class, not the base class! Moreover, if we have many different derived classes, the system will find the correct function for the object that the pointer points to. This is called late binding, or dynamic binding.

bugle toot Brass joe(bugle, toot); String mary(harp, strummm); Percussion bill(kettle, whomp); Instrument* instr; instr = &joe; instr->play( ); instr = &mary; instr->play( ); instr = &bill; instr->play( ); harp strumm kettle whomp instr joe mary bill

bugle toot Brass joe(bugle, toot); String mary(harp, strummm); Percussion bill(kettle, whomp); Instrument* instr; instr = &joe; instr->play( ); instr = &mary; instr->play( ); instr = &bill; instr->play( ); harp strumm kettle whomp instr joe mary bill

bugle toot Brass joe(bugle, toot); String mary(harp, strummm); Percussion bill(kettle, whomp); Instrument* instr; instr = &joe; instr->play( ); instr = &mary; instr->play( ); instr = &bill; instr->play( ); harp strumm kettle whomp instr joe mary bill

Foo Bar Widget

Foo Bar Widget # myData : string printMyData( ) : void - barData1 : string + printMyData( ) : void - widgetData1 : string + printMyData( ) : void

Foo Bar Widget # myData : string + printMyData( ) : void - barData1 : string + printMyData( ) : void - widgetData1 : string + printMyData( ) : void void printMydata( ) { cout << I am a Foo object, my data is << myData << endl; }

Foo Bar Widget # myData : string + printMyData( ) : void - barData : string + printMyData( ) : void - widgetData2 : string + printMyData( ) : void void printMydata( ) { cout << I am a Bar object, my data is << myData << barData << endl; } myData is visible to the child class

Foo Bar Widget # myData : string + printMyData( ) : void - barData : string + printMyData( ) : void - widgetData : string + printMyData( ) : void void printMydata( ) { cout << I am a Widget object, my data is << myData << widgetData << endl; }

What will the following do? Foo foo (C++ Rocks); Bar bar (Prof deBry, Rocks?); Widget widget(I Love, C++); foo.printMyData( ); bar.printMyData( ); widget.printMyData( );

But …What will the following do? Foo *fooPtrs[3]; fooPtrs[0] = &foo; fooPtrs[1] = &bar; fooPtrs[2] = &widget; fooPtrs[0]->printMyData( ); fooPtrs[1]->printMyData( ); fooPtrs[2]->printMyData( );

What will the following do? Make printMyData( ) virtual Foo *fooPtrs[3]; fooPtrs[0] = &foo; fooPtrs[1] = &bar; fooPtrs[2] = &widget; fooPtrs[0]->printMyData( ); fooPtrs[1]->printMyData( ); fooPtrs[2]->.printMyData( );

Try it …

Rules for Polymorphism In the base class, the keyword virtual must precede any function that you want to call using polymorphism. In the derived class the signature must exactly match the signature of the function being over-ridden. If the signature is different, the compiler considers it to be a different function, not an over-riding function. The actual implementation of the function in the derived class will be different than that in the base class. The function is invoked through a base class pointer that contains the address of the derived class object.

Pure Virtual Functions In the previous example, we provided an implementation for the printMyData( ) function in the base class. Often times you will not need to provide an implementation for a virtual function in the base class. You can do this by making the function a pure virtual function. Pure virtual functions have no implementation.

class Foo { public: virtual void printMyData( ) const = 0; protected: string myData; } the =0 notation signals that this is a pure virtual function. There should be no implementation of this function written.

Abstract Classes If a class contains at least one pure virtual function then it is impossible to create an object of that class. Why? Such classes are called abstract classes.

Virtual Destructors If an object is destroyed by applying the delete operator to a base class pointer, only the base class destructor is called. This can leave derived class data members on the heap with no way to delete them. This problem is solved by making the destructor in the base class virtual. Polymorphism then causes the derived class destructor to be called first. It will automatically call the base class destructor, insuring that all data is properly removed from the heap.

V-Tables When the compiler encounters a class definition that contains virtual functions, it builds a v-table for that class. The v-table contains the addresses of all of the virtual functions for the class. class Instrument { public: int getValue( ); virtual void play ( ); virtual void display ( ); virtual ~Instrument ( ); }; Instruments v-table play ( ) ~Instrument( ) Instrument::play Instrument:: ~Instrument display( ) Instrument::display

When the compiler encounters a derived class definition that inherits publicly from this base class, it copies the v-table from the base class for the derived class. class Brass : public Instrument { public: void play ( ); void display ( int ); ~Brass ( ); }; Brasss v-table play ( ) ~Instrument( ) Instrument::play Instrument:: ~Instrument display( ) Instrument::display

Now, for any function in the derived class that over-rides a virtual function in the base class, the compiler sets the address for that function to the derived class functions address. class Brass { public: Brasss v-table play ( ) ~Instrument( ) Instrument::play Instrument:: ~Instrument display( ) Instrument::display void play ( ); Brass::play( ) void display( int); ~Brass( ); Brass::~Brass( ) the signature of the display function does not match the one in the base class, so no change is made to the v-table.

Brasss v-table play ( ) ~Instrument( ) display( ) Instrument::display( ) Brass::play( ) Brass::~Brass( ) Now, when an object of the derived class is created a pointer to the classs v-table is added to the object. Instrument* orchestra = new Brass( … some parameters…); member data The Brass object

The address of the object is saved in a base class pointer Brasss v-table play ( ) ~Instrument( ) display( ) Instrument::display( ) Brass::play( ) Brass::~Brass( ) myTuba member data orchestra Instrument* iPtr = new Brass( … some parameters…);

Invoke the play( ) function Brasss v-table play ( ) ~Instrument( ) display( ) Instrument::display( ) Brass::play( ) Brass::~Brass( ) myTuba member data orchestra -> play ( ); orchestra 1. the pointer is dereferenced to find the object. 2. the pointer to the v-table is located in the object. 3. This pointer is dereferenced to access the v-table 4. the play( ) function is located in the v-table and the corresponding address is used to invoke the play function.

What happens now if you want to invoke the display (int) function from the Brass class? class Brass { public: void play ( ); void display ( int ); ~Brass ( ); }; Brasss v-table play ( ) ~Instrument( ) Instrument::play Instrument:: ~Instrument display( ) Instrument::display the function display (int) was not defined in the base class, and it is not virtual, so it is not in the v-table.

So, if you write orchestra -> display ( 5 ); You will get a compiler error, because Orchestra is a base class pointer, and the function display ( int ) is not defined in the base class.

As you have seen, when you store the address of a derived class object in a base class pointer, you lose information about the class that the object belongs to. Thus, it seems impossible to invoke the derived class function display (int) with the statement orchestra -> display (5);

We could cast the pointer to a derived class pointer … but what if we are not sure that the object being pointed to really is an object of the Brass class?

Run Time Type Identification Run Time Type Identification (RTTI) provides a way to find out what kind of an object is pointed to by a base class pointer. To find the type of object being pointed to, we use a special function typeid ( ). To use this function we must #include.

Instrument virtual void play( ) Brass virtual void play( ) void play (int) Percussion virtual void play( ) Woodwind virtual void play( ) Consider the inheritance hierarchy …

And suppose you have the following situation: Instrument *orchestra[3]; orchestra[0] = new Brass ( some parameters ); orchestra[1] = new Percussion ( some parameters ); orchestra[2] = new Woodwind ( some parameters ); … and you want to execute the line orchestra[0]->display(37);

Since orchestra[0] contains a base class pointer and play(int) is not in the v-table … orchestra[0]->play(37); will give you a compiler error So … how do you execute Brass class play(int) function?

We can determine whether or not an object pointed to in the array of base class pointers is a Brass instrument by writing for (int i = 0; i < 3; i++ ) { if ((typeid (*orchestra[i])) == typeid (Brass)) { // code } dereference the pointer and get the typeid of what it points to. then compare it with the typeid of the Brass class.

If we determine that the object pointed to is, in fact, an object of the Brass class, then we can downcast the pointer and invoke the derived class function. In this case we use a dynamic cast. The dynamic cast checks at run time to be sure that the cast is safe. Dynamic Casting dynamic_cast (orchestra[i]) -> play (5); this is a base class pointer this casts the pointer to a Brass pointer and we can now invoke the play (int) function!

Notes There is some overhead involved with the use of RTTI The typeid function should only be used for comparisons Dynamic casting also involves some overhead Dynamic casting only works with pointers