Presentation is loading. Please wait.

Presentation is loading. Please wait.

Copyright 2006 Pearson Addison-Wesley, 2008, 2009, 2013 Joey Paquet 6-1 Concordia University Department of Computer Science and Software Engineering COMP345.

Similar presentations


Presentation on theme: "Copyright 2006 Pearson Addison-Wesley, 2008, 2009, 2013 Joey Paquet 6-1 Concordia University Department of Computer Science and Software Engineering COMP345."— Presentation transcript:

1 Copyright 2006 Pearson Addison-Wesley, 2008, 2009, 2013 Joey Paquet 6-1 Concordia University Department of Computer Science and Software Engineering COMP345 – Advanced program design with C++ Slide set 6: virtual functions, abstract classes, the slicing problem, polymorphism, function pointers, virtual function tables

2 Copyright 2006 Pearson Addison-Wesley, 2008, 2009, 2013 Joey Paquet 6-2 Learning Objectives  Virtual Function Basics  Late binding  Implementing virtual functions  When to use a virtual function  Abstract classes and pure virtual functions  Pointers and Virtual Functions  Extended type compatibility  Downcasting and upcasting  The slicing problem  C++ "under the hood" with virtual functions

3 Copyright 2006 Pearson Addison-Wesley, 2008, 2009, 2013 Joey Paquet 6-3 Virtual Function Basics  Polymorphism  Associating many meanings to one function  Virtual functions provide this capability  Fundamental principle of object-oriented programming!  Virtual  Existing in "essence" though not in fact  Virtual Function  Can be "used" before it’s "defined"

4 Copyright 2006 Pearson Addison-Wesley, 2008, 2009, 2013 Joey Paquet 6-4 Figures Example  Best explained by example:  Classes for several kinds of figures  Rectangles, circles, ovals, etc.  Each figure an object of different class  Rectangle data: height, width, center point  Circle data: center point, radius  All derive from one parent-class: Figure  Require function: draw()  Different instructions for each figure

5 Copyright 2006 Pearson Addison-Wesley, 2008, 2009, 2013 Joey Paquet 6-5 Figures Example 2  Each class needs a different draw function  Can be called "draw" in each class, so: Rectangle r; Circle c; r.draw(); //Calls Rectangle’s draw c.draw(); //Calls Circle’s draw  Nothing new here yet…

6 Copyright 2006 Pearson Addison-Wesley, 2008, 2009, 2013 Joey Paquet 6-6 Figures Example: center()  Parent class Figure contains functions that apply to "all" figures; consider: center() : moves a figure to center of the screen  Erases 1 st, then re-draws  So Figure::center() would use function draw() to re- draw  Complications!  Which draw() function?  From which class?

7 Copyright 2006 Pearson Addison-Wesley, 2008, 2009, 2013 Joey Paquet 6-7 Figures Example: New Figure  Consider a new kind of figure coming along: Triangle class derived from Figure class  Function center() inherited from Figure  Will it work for triangles?  It uses draw(), which is different for each figure  It will use Figure::draw()  won’t work for triangles  Want inherited function center() to use function Triangle::draw() and NOT function Figure::draw()  But class Triangle wasn’t even WRITTEN when Figure::center() was! Doesn’t know "triangles"!

8 Copyright 2006 Pearson Addison-Wesley, 2008, 2009, 2013 Joey Paquet 6-8 Figures Example: Virtual  Virtual functions are the answer  Tells compiler:  "Don’t know how function is implemented"  "Wait until used in program"  "Then get implementation from the type of the object instance“  Called late binding or dynamic binding  Virtual functions are implemented using late binding

9 Copyright 2006 Pearson Addison-Wesley, 2008, 2009, 2013 Joey Paquet 6-9 Virtual Functions: Example 2  Bigger example best to demonstrate  Record-keeping program for automotive parts store  Track sales  Don’t know all types of sales yet  1 st only regular retail sales  Later: Discount sales, mail-order, etc.  Depend on other factors besides just price, tax

10 Copyright 2006 Pearson Addison-Wesley, 2008, 2009, 2013 Joey Paquet 6-10 Virtual Functions: Auto Parts  Program must:  Compute daily gross sales  Calculate largest/smallest sales of day  Perhaps average sale for day  All come from individual bills  But many functions for computing bills will be added "later” when different types of sales are added  So function for "computing a bill" will be virtual!

11 Copyright 2006 Pearson Addison-Wesley, 2008, 2009, 2013 Joey Paquet 6-11 Class Sale class Sale { public: Sale(); Sale(double thePrice); double getPrice() const; virtual double bill() const; double savings(const Sale& other) const; private: double price; };

12 Copyright 2006 Pearson Addison-Wesley, 2008, 2009, 2013 Joey Paquet 6-12 Class Sale double Sale::savings(const Sale& other) const { return (bill() – other.bill()); } bool operator < (const Sale& first, const Sale& second) { return (first.bill() < second.bill()); }  Notice BOTH use member function bill()

13 Copyright 2006 Pearson Addison-Wesley, 2008, 2009, 2013 Joey Paquet 6-13 Class Sale  Represents sales of single item with no added discounts or charges.  Notice reserved word virtual in declaration of member function bill()  Impact: Later, derived classes of Sale can define THEIR versions of function bill()  Other member functions of Sale will use version based on object of derived class!  They won’t automatically use Sale ’s version!

14 Copyright 2006 Pearson Addison-Wesley, 2008, 2009, 2013 Joey Paquet 6-14 Derived Class DiscountSale class DiscountSale : public Sale { public: DiscountSale(); DiscountSale(double thePrice, double theDiscount); double getDiscount() const; void setDiscount(double newDiscount); double bill() const; private: double discount; };

15 Copyright 2006 Pearson Addison-Wesley, 2008, 2009, 2013 Joey Paquet 6-15 DiscountSale ’s bill() function double DiscountSale::bill() const { double fraction = discount/100; return (1 - fraction)*getPrice(); }  Qualifier virtual does not go in actual function definition  "Automatically" virtual in derived class  Declaration (in interface) not required to have virtual keyword either (but usually does)

16 Copyright 2006 Pearson Addison-Wesley, 2008, 2009, 2013 Joey Paquet 6-16 Derived Class DiscountSale  DiscountSale ’s member function bill() implemented differently than Sale ’s  Particular to " discount s“  Member functions savings and operator <  Will use this definition of bill() for all objects of DiscountSale class  Instead of "defaulting" to version defined in Sales class

17 Copyright 2006 Pearson Addison-Wesley, 2008, 2009, 2013 Joey Paquet 6-17 Virtual: Powerful!  Recall class Sale written long before derived class DiscountSale  Member savings and operator < compiled before even had the idea of a DiscountSale class  Yet in a call like: DiscountSale d1, d2; d1.savings(d2);  Call in savings() to function bill() knows to use definition of bill() from DiscountSale class  Powerful!

18 Copyright 2006 Pearson Addison-Wesley, 2008, 2009, 2013 Joey Paquet 6-18 Virtual: How?  Involves late binding  Virtual functions implement late binding  Tells the compiler to "wait" until the function is used in the program during execution  At run-time, decide which definition to use based on the type of the calling object  Very important OOP principle!

19 Copyright 2006 Pearson Addison-Wesley, 2008, 2009, 2013 Joey Paquet 6-19 Overriding  Virtual function definition changed in a derived class  We say it’s been "overidden“  Similar to redefined  Recall: for standard functions  So:  Virtual functions changed: overridden  Non-virtual functions changed: redefined

20 Copyright 2006 Pearson Addison-Wesley, 2008, 2009, 2013 Joey Paquet 6-20 Virtual Functions: Why Not All?  Clear advantages to virtual functions as we’ve seen  One major disadvantage: overhead!  Uses more storage  Late binding is "on the fly", so programs run slower  See next slides for explanations  So if virtual functions are not needed, they should not be used  In Java, all methods behave like C++ virtual methods!

21 Copyright 2006 Pearson Addison-Wesley, 2008, 2009, 2013 Joey Paquet 6-21 Pure Virtual Functions  Base class might not have "meaningful" definition for some of its members!  Its purpose solely for others to derive from  Recall class Figure  All figures are objects of derived classes  Rectangles, circles, triangles, etc.  Class Figure has no generic way to draw()  Make it a pure virtual function: virtual void draw() = 0;

22 Copyright 2006 Pearson Addison-Wesley, 2008, 2009, 2013 Joey Paquet 6-22 Abstract Base Classes  Pure virtual functions require no definition  Forces all derived classes to define "their own" version  Class with one or more pure virtual functions is: abstract base class  Can only be used as base class  No objects can ever be created from it  Since it doesn’t have complete "definitions" of all its members!  If derived class fails to define all its inherited pure virtual functions (or introduces one or more):  It’s an abstract base class too

23 Copyright 2006 Pearson Addison-Wesley, 2008, 2009, 2013 Joey Paquet 6-23 Extended Type Compatibility  Given: Derived is derived class of Base  Derived objects can be assigned to objects of type Base  But NOT the other way!  Consider previous example:  A DiscountSale "is a" Sale, but reverse not true

24 Copyright 2006 Pearson Addison-Wesley, 2008, 2009, 2013 Joey Paquet 6-24 Extended Type Compatibility class Pet { public: string name; virtual void print() const; }; class Dog : public Pet { public: string breed; virtual void print() const; };

25 Copyright 2006 Pearson Addison-Wesley, 2008, 2009, 2013 Joey Paquet 6-25 Classes Pet and Dog  Now given declarations: Dog vdog; Pet vpet;  Notice member variables name and breed are public!  For example purposes only! Not typical!

26 Copyright 2006 Pearson Addison-Wesley, 2008, 2009, 2013 Joey Paquet 6-26 Using Classes Pet and Dog  Anything that "is a" Dog "is a" Pet : vdog.name = "Tiny"; vdog.breed = "Great Dane"; vpet = vdog;  These are allowable  Can assign values to parent-types, but not reverse  A Pet "is not a" Dog (not necessarily)

27 Copyright 2006 Pearson Addison-Wesley, 2008, 2009, 2013 Joey Paquet 6-27 Slicing Problem  Notice value assigned to vpet "loses" it’s breed field!  cout << vpet.breed;  Produces ERROR msg!  Called the slicing problem  Might seem appropriate  Dog was moved to Pet variable, so it should be treated like a Pet  And therefore not have "dog" properties

28 Copyright 2006 Pearson Addison-Wesley, 2008, 2009, 2013 Joey Paquet 6-28 Slicing Problem : Fix  In C++, the slicing problem is nuisance  vdog is still "is a" Great Dane named Tiny  We’d like to refer to it’s breed even if it’s been treated as a Pet  Can do so with pointers to dynamic variables

29 Copyright 2006 Pearson Addison-Wesley, 2008, 2009, 2013 Joey Paquet 6-29 Slicing Problem Example Pet *ppet; Dog *pdog; pdog = new Dog; pdog->name = "Tiny"; pdog->breed = "Great Dane"; ppet = pdog;  Still cannot access breed field of object pointed to by ppet : cout breed;//ILLEGAL!  Because ppet is a pointer to type Pet  However, the ppet object pointed to still has a value for breed (it has not been sliced out)

30 Copyright 2006 Pearson Addison-Wesley, 2008, 2009, 2013 Joey Paquet 6-30 Slicing Problem Example  If we use the virtual member function: ppet->print();  Calls print member function in Dog class!  Because it’s virtual  print() can then use breed !  C++ "waits" to see what object pointer ppet is actually pointing to before "binding" the call

31 Copyright 2006 Pearson Addison-Wesley, 2008, 2009, 2013 Joey Paquet 6-31 Virtual Destructors  Recall: destructors needed to de-allocate dynamically allocated data  Consider: Base *pBase = new Derived; … delete pBase;  Would call Base class destructor even though pointing to Derived class object!  Making destructor virtual fixes this!  Good policy for all destructors to be virtual

32 Copyright 2006 Pearson Addison-Wesley, 2008, 2009, 2013 Joey Paquet 6-32 Upcasting  Consider: Pet vpet; Dog vdog; … vdog = static_cast (vpet); //ILLEGAL!  Can’t cast a Pet to be a Dog, but: vpet = vdog; // Legal! vpet = static_cast (vdog); // Also legal!  Upcasting is OK  From descendant type to ancestor type

33 Copyright 2006 Pearson Addison-Wesley, 2008, 2009, 2013 Joey Paquet 6-33 Downcasting  Downcasting dangerous!  Casting from ancestor type to descended type  Assumes information is "added"  Can be done with dynamic_cast : Pet *ppet; ppet = new Dog; Dog *pdog = dynamic_cast (ppet);  Legal, but dangerous!  Downcasting rarely done due to pitfalls  Must track all information to be added  All member functions must be virtual

34 Copyright 2006 Pearson Addison-Wesley, 2008, 2009, 2013 Joey Paquet 6-34 Virtual Functions: Inner Workings  Don’t need to know how to use it!  Principle of information hiding  Virtual function table  Compiler creates it  Has pointers for each virtual member function  Points to location of correct code for that function  Function pointers are updated at run-time depending on type conversions or dynamic polymorphism using pointers.  Objects of such classes have a (hidden) pointer:  Points to virtual function table (VTABLE)  Upon call to these functions, the pointer is followed to the table, then the right function is called, through the function pointer.  Thus, it requires more memory, and more execution time

35 Function Pointers  Function Pointers are pointers, i.e. variables, which point to the starting address of a function’s code.  Enables the call to different functions, depending on the function pointer value, which can be pointing to different functions’ code in time.  In C++, a function pointer can only point to different functions with the same signature (single dispatch)  double/multiple dispatch – dispatch to any function (independent of signature), with a an elaborated mechanism for mapping parameters/return value. Copyright 2006 Pearson Addison-Wesley, 2008, 2009, 2013 Joey Paquet 6-35

36 Function Pointers: Example float Plus (float a, float b) { return a+b; } float Minus (float a, float b) { return a-b; } float Multiply(float a, float b) { return a*b; } float Divide (float a, float b) { return a/b; } // Solution with a switch-statement - specifies which operation to execute void Switch(float a, float b, char opCode) { float result; // execute operation switch(opCode) { case '+' : result = Plus (a, b); break; case '-' : result = Minus (a, b); break; case '*' : result = Multiply (a, b); break; case '/' : result = Divide (a, b); break; } cout << "Switch: 2+5=" << result << endl; // display result } Copyright 2006 Pearson Addison-Wesley, 2008, 2009, 2013 Joey Paquet 6-36

37 Function Pointers: Example // Solution with a function pointer – // is a function pointer and points to a function // which takes two floats and returns a float. // The function pointer points to which operation shall be executed. void Switch_With_Function_Pointer(float a, float b, float (*pt2Func)(float, float)) { float result = pt2Func(a, b); // call using function pointer cout << "Switch replaced by function pointer: 2-5="; cout << result << endl; } // Execute example code void Replace_A_Switch() { cout << endl << "Executing function 'Replace_A_Switch'" << endl; Switch(2, 5, '+'); Switch_With_Function_Pointer(2, 5, &Minus); } Copyright 2006 Pearson Addison-Wesley, 2008, 2009, 2013 Joey Paquet 6-37

38 Copyright 2006 Pearson Addison-Wesley, 2008, 2009, 2013 Joey Paquet 6-38 Late binding: VTABLES #include using namespace std; class NoVirtual { int a; public: void x() const {} int i() const { return 1; } }; class OneVirtual { int a; public: virtual void x() const {} int i() const { return 1; } }; class TwoVirtuals { int a; public: virtual void x() const {} virtual int i() const { return 1; } }; int main() { cout << "int: " << sizeof(int) << endl; cout << "NoVirtual: “ << sizeof(NoVirtual) << endl; cout << "void* : " << sizeof(void*) << endl; cout << "OneVirtual: “ << sizeof(OneVirtual) << endl; cout << "TwoVirtuals: “ << sizeof(TwoVirtuals) << endl; } Execution: int: 4 NoVirtual: 4 void*: 4 OneVirtual: 8 TwoVirtuals: 8

39 Copyright 2006 Pearson Addison-Wesley, 2008, 2009, 2013 Joey Paquet 6-39 Late binding: VTABLES //http://www.linuxtopia.org/online_books/ programming_books/thinking_in_c++/Chapter 15_006.html #include using namespace std; enum note { middleC, Csharp, Cflat }; // Etc. class Instrument { public: virtual void play(note) const { cout << "Instrument::play" << endl; } virtual char* what() const { return "Instrument"; } // Assume this will modify the object: virtual void adjust(int) {} }; class Wind : public Instrument { public: void play(note) const { cout << "Wind::play" << endl; } char* what() const { return "Wind"; } void adjust(int) { cout << "Wind::adjust" << endl; } }; class Percussion : public Instrument { public: void play(note) const { cout << "Percussion::play" << endl; } char* what() const { return "Percussion"; } void adjust(int) {} }; class Stringed : public Instrument { public: void play(note) const { cout << "Stringed::play" << endl; } char* what() const { return "Stringed"; } void adjust(int) {} };

40 Copyright 2006 Pearson Addison-Wesley, 2008, 2009, 2013 Joey Paquet 6-40 Late binding: VTABLES class Brass : public Wind { public: void play(note) const cout << "Brass::play" << endl } char* what() const { return "Brass"; } }; class Woodwind : public Wind { public: void play(note) const { cout << "Woodwind::play" << endl; } char* what() const { return "Woodwind"; } }; void tune(Instrument& i) { //... i.play(middleC); } void f(Instrument& i) { i.adjust(1); } int main() { // Upcasting during array initialization: Instrument* A[] = { new Wind, new Percussion, new Stringed, new Brass, }; Wind flute; Percussion drum; Stringed violin; Brass flugelhorn; Woodwind recorder; tune(flute); tune(drum); tune(violin); tune(flugelhorn); tune(recorder); f(flugelhorn); }

41 Copyright 2006 Pearson Addison-Wesley, 2008, 2009, 2013 Joey Paquet 6-41 Late binding: VTABLES

42 Copyright 2006 Pearson Addison-Wesley, 2008, 2009, 2013 Joey Paquet 6-42 Summary 1  Late binding delays decision of which member function is called until runtime  In C++, virtual functions use late binding  Pure virtual functions have no definition  Classes with at least one are abstract  No objects can be created from abstract class  Used strictly as base for others to derive

43 Copyright 2006 Pearson Addison-Wesley, 2008, 2009, 2013 Joey Paquet 6-43 Summary 2  Derived class objects can be assigned to base class objects  Base class members are lost; slicing problem  Pointer assignments and dynamic objects  Allow "fix" to slicing problem  Make all destructors virtual  Good programming practice  Ensures memory correctly de-allocated

44 Copyright 2006 Pearson Addison-Wesley, 2008, 2009, 2013 Joey Paquet 6-44 References  How C++ implements late binding: http://www.linuxtopia.org/online_books/programming_ books/thinking_in_c++/Chapter15_007.htm http://www.linuxtopia.org/online_books/programming_ books/thinking_in_c++/Chapter15_007.htm  The function pointer tutorials: http://www.newty.de/fpt/intro.html


Download ppt "Copyright 2006 Pearson Addison-Wesley, 2008, 2009, 2013 Joey Paquet 6-1 Concordia University Department of Computer Science and Software Engineering COMP345."

Similar presentations


Ads by Google