Download presentation
Presentation is loading. Please wait.
Published byShawn Craig Modified over 8 years ago
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
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.