ObjectOriented Programming Polymorphism Outline 10 1 Introduction 10
Object-Oriented Programming: Polymorphism Outline 10. 1 Introduction 10. 2 Relationships Among Objects in an Inheritance Hierarchy 10. 2. 1 Invoking Base-Class Functions from Derived-Class Objects 10. 2. 2 Aiming Derived-Class Pointers at Base-Class Objects 10. 2. 3 Derived-Class Member-Function Calls via Base-Class Pointers 10. 2. 4 Virtual Functions 10. 3 Polymorphism Examples 10. 4 Type Fields and switch Structures 10. 5 Abstract Classes 10. 6 Case Study: Inheriting Interface and Implementation 10. 7 Polymorphism, Virtual Functions and Dynamic Binding “Under the Hood” 10. 8 Virtual Destructors 2003 Prentice Hall, Inc. All rights reserved. 1
2 10. 1 Introduction • Polymorphism – “Program in the general” – Treat objects in same class hierarchy as if all base class – Virtual functions and dynamic binding • Will explain how polymorphism works – Makes programs extensible • New classes added easily, can still be processed • In our examples – Use abstract base class Shape • Defines common interface (functionality) • Point, Circle and Cylinder inherit from Shape – Class Employee for a natural example 2003 Prentice Hall, Inc. All rights reserved.
10. 2 Relationships Among Objects in an Inheritance Hierarchy • Previously (Section 9. 4), – Circle inherited from Point – Manipulated Point and Circle objects using member functions • Now – Invoke functions using base-class/derived-class pointers – Introduce virtual functions • Key concept – Derived-class object can be treated as base-class object • “is-a” relationship • Base class is not a derived class object 2003 Prentice Hall, Inc. All rights reserved. 3
10. 2. 1 Invoking Base-Class Functions from Derived-Class Objects • Aim pointers (base, derived) at objects (base, derived) – Base pointer aimed at base object – Derived pointer aimed at derived object • Both straightforward – Base pointer aimed at derived object • “is a” relationship – Circle “is a” Point • Will invoke base class functions – Function call depends on the class of the pointer/handle • Does not depend on object to which it points • With virtual functions, this can be changed (more later) 2003 Prentice Hall, Inc. All rights reserved. 4
1 2 3 4 // Fig. 10. 1: point. h // Point class definition represents an x-y coordinate pair. #ifndef POINT_H #define POINT_H 5 6 class Point { 7 8 9 public: Point( int = 0, int = 0 ); // default constructor 10 11 12 13 14 15 16 17 void set. X( int ); int get. X() const; // set x in coordinate pair // return x from coordinate pair void set. Y( int ); int get. Y() const; // set y in coordinate pair // return y from coordinate pair void print() const; 18 19 20 21 private: int x; int y; 22 23 }; // end class Point 24 25 #endif Base class print function. Outline point. h (1 of 1) // output Point object // x part of coordinate pair // y part of coordinate pair 2003 Prentice Hall, Inc. All rights reserved. 5
1 2 3 // Fig. 10. 2: point. cpp // Point class member-function definitions. #include <iostream> 4 5 using std: : cout; 6 7 #include "point. h" 8 9 10 11 12 13 // default constructor Point: : Point( int x. Value, int y. Value ) : x( x. Value ), y( y. Value ) { // empty body 14 15 } // end Point constructor 16 17 18 19 20 // set x in coordinate pair void Point: : set. X( int x. Value ) { x = x. Value; // no need for validation 21 22 } // end function set. X Outline // Point class definition point. cpp (1 of 2) 23 2003 Prentice Hall, Inc. All rights reserved. 6
24 25 26 27 // return x from coordinate pair int Point: : get. X() const { return x; 28 29 } // end function get. X 30 31 32 33 34 // set y in coordinate pair void Point: : set. Y( int y. Value ) { y = y. Value; // no need for validation 35 36 } // end function set. Y 37 38 39 40 41 // return y from coordinate pair int Point: : get. Y() const { return y; 42 43 44 45 46 47 48 49 50 } // end function get. Y Outline point. cpp (2 of 2) Output the x, y coordinates of the Point. // output Point object void Point: : print() const { cout << '[' << get. X() << ", " << get. Y() << ']'; } // end function print 2003 Prentice Hall, Inc. All rights reserved. 7
1 2 3 4 // Fig. 10. 3: circle. h // Circle class contains x-y coordinate pair and radius. #ifndef CIRCLE_H #define CIRCLE_H 5 6 #include "point. h" 7 8 class Circle : public Point { 9 10 public: Outline // Point class definition 11 12 13 // default constructor Circle( int = 0, double = 14 15 16 void set. Radius( double ); double get. Radius() const; 17 18 19 20 double get. Diameter() const; double get. Circumference() const; double get. Area() const; 21 22 void print() const; 23 24 25 private: double radius; 26 27 }; // end class Circle 28 29 #endif Circle inherits from Point, but redefines its print 0. 0 ); function. circle. h (1 of 1) // set radius // return diameter // return circumference // return area // output Circle object // Circle's radius 2003 Prentice Hall, Inc. All rights reserved. 8
1 2 3 // Fig. 10. 4: circle. cpp // Circle class member-function definitions. #include <iostream> 4 5 using std: : cout; 6 7 #include "circle. h" 8 9 10 11 12 13 // default constructor Circle: : Circle( int x. Value, int y. Value, double radius. Value ) : Point( x. Value, y. Value ) // call base-class constructor { set. Radius( radius. Value ); 14 15 } // end Circle constructor 16 17 18 19 20 // set radius void Circle: : set. Radius( double radius. Value ) { radius = ( radius. Value < 0. 0 ? 0. 0 : radius. Value ); 21 22 } // end function set. Radius Outline // Circle class definition circle. cpp (1 of 3) 23 2003 Prentice Hall, Inc. All rights reserved. 9
24 25 26 27 // return radius double Circle: : get. Radius() const { return radius; 28 29 } // end function get. Radius 30 31 32 33 34 // calculate and return diameter double Circle: : get. Diameter() const { return 2 * get. Radius(); 35 36 } // end function get. Diameter 37 38 39 40 41 // calculate and return circumference double Circle: : get. Circumference() const { return 3. 14159 * get. Diameter(); 42 43 } // end function get. Circumference 44 45 46 47 48 // calculate and return area double Circle: : get. Area() const { return 3. 14159 * get. Radius(); 49 50 } // end function get. Area Outline circle. cpp (2 of 3) 2003 Prentice Hall, Inc. All rights reserved. 10
51 52 53 54 55 56 57 58 59 Circle redefines its print // output Circle object function. It calls Point’s void Circle: : print() const print function to output the x, y { cout << "center = "; coordinates of the center, then Point: : print(); // invoke Point's print function prints the radius. cout << "; radius = " << get. Radius(); Outline } // end function print circle. cpp (3 of 3) 2003 Prentice Hall, Inc. All rights reserved. 11
1 2 3 4 // Fig. 10. 5: fig 10_05. cpp // Aiming base-class and derived-class pointers at base-class // and derived-class objects, respectively. #include <iostream> 5 6 7 8 using std: : cout; using std: : endl; using std: : fixed; 9 10 #include <iomanip> 11 12 using std: : setprecision; 13 14 15 #include "point. h" #include "circle. h" 16 17 18 19 20 int main() { Point point( 30, 50 ); Point *point. Ptr = 0; 21 22 23 // Point class definition // Circle class definition Outline fig 10_05. cpp (1 of 3) // base-class pointer Circle circle( 120, 89, 2. 7 ); Circle *circle. Ptr = 0; // derived-class pointer 24 2003 Prentice Hall, Inc. All rights reserved. 12
25 26 // set floating-point numeric formatting Use objects and pointers to cout << fixed << setprecision( 2 ); call the print function. The 27 28 29 30 31 32 33 pointers and objects are of the // output objects point and circle same class, so the proper cout << "Print point and circle objects: " print function is called. Outline << "n. Point: "; point. print(); // invokes Point's print cout << "n. Circle: "; circle. print(); // invokes Circle's print 34 35 36 37 38 39 40 // aim base-class pointer at base-class object and print point. Ptr = &point; cout << "nn. Calling print with base-class pointer to " << "nbase-class object invokes base-class print " << "function: n"; point. Ptr->print(); // invokes Point's print 41 42 43 44 45 46 47 48 // aim derived-class pointer at // and print circle. Ptr = &circle; cout << "nn. Calling print with << "nderived-class object << "print function: n"; circle. Ptr->print(); // invokes fig 10_05. cpp (2 of 3) derived-class object derived-class pointer to " invokes derived-class " Circle's print 49 2003 Prentice Hall, Inc. All rights reserved. 13
50 51 52 53 54 55 56 // aim base-class pointer at derived-class object and print point. Ptr = &circle; cout << "nn. Calling print with base-class pointer to " << "derived-class objectninvokes base-class print " << "function on that derived-class object: n" ; point. Ptr->print(); // invokes Point's print cout << endl; 57 58 return 0; 59 60 } // end main Aiming a base-class pointer at a derived object is allowed (the Circle “is a” Point). However, it calls Point’s print function, determined by the pointer type. virtual functions allow us to change this. Outline fig 10_05. cpp (3 of 3) 2003 Prentice Hall, Inc. All rights reserved. 14
Print point and circle objects: Point: [30, 50] Circle: center = [120, 89]; radius = 2. 70 Outline Calling print with base-class pointer to base-class object invokes base-class print function: [30, 50] Calling print with derived-class pointer to derived-class object invokes derived-class print function: center = [120, 89]; radius = 2. 70 Calling print with base-class pointer to derived-class object invokes base-class print function on that derived-class object: [120, 89] fig 10_05. cpp output (1 of 1) 2003 Prentice Hall, Inc. All rights reserved. 15
10. 2. 2 Aiming Derived-Class Pointers at Base-Class Objects • Previous example – Aimed base-class pointer at derived object • Circle “is a” Point • Aim a derived-class pointer at a base-class object – Compiler error • No “is a” relationship • Point is not a Circle • Circle has data/functions that Point does not – set. Radius (defined in Circle) not defined in Point – Can cast base-object’s address to derived-class pointer • Called downcasting (more in 10. 9) • Allows derived-class functionality 2003 Prentice Hall, Inc. All rights reserved. 16
1 2 3 4 // Fig. 10. 6: fig 10_06. cpp // Aiming a derived-class pointer at a base-class object. #include "point. h" // Point class definition #include "circle. h" // Circle class definition 5 6 7 8 9 int main() { Point point( 30, 50 ); Circle *circle. Ptr = 0; 10 11 12 // aim derived-class pointer at base-class object circle. Ptr = &point; // Error: a Point is not a Circle 13 14 return 0; 15 16 } // end main C: cpphtp 4examplesch 10fig 10_06Fig 10_06. cpp(12) : error C 2440: '=' : cannot convert from 'class Point *' to 'class Circle *' Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast Outline fig 10_06. cpp (1 of 1) fig 10_06. cpp output (1 of 1) 2003 Prentice Hall, Inc. All rights reserved. 17
10. 2. 3 Derived-Class Member-Function Calls via Base-Class Pointers • Handle (pointer/reference) – Base-pointer can aim at derived-object • But can only call base-class functions – Calling derived-class functions is a compiler error • Functions not defined in base-class • Common theme – Data type of pointer/reference determines functions it can call 2003 Prentice Hall, Inc. All rights reserved. 18
1 2 3 4 5 // Fig. 10. 7: fig 10_07. cpp // Attempting to invoke derived-class-only member functions // through a base-class pointer. #include "point. h" // Point class definition #include "circle. h" // Circle class definition 6 7 8 9 10 int main() { Point *point. Ptr = 0; Circle circle( 120, 89, 2. 7 ); 11 12 13 // aim base-class pointer at derived-class object point. Ptr = &circle; 14 15 16 17 18 19 20 21 // invoke base-class member functions on derived-class // object through base-class pointer int x = point. Ptr->get. X(); int y = point. Ptr->get. Y(); point. Ptr->set. X( 10 ); point. Ptr->set. Y( 10 ); point. Ptr->print(); Outline fig 10_07. cpp (1 of 2) 22 2003 Prentice Hall, Inc. All rights reserved. 19
23 24 25 26 27 28 29 // attempt to invoke derived-class-only member functions // on derived-class object through base-class pointer double radius = point. Ptr->get. Radius(); point. Ptr->set. Radius( 33. 33 ); double diameter = point. Ptr->get. Diameter(); double circumference = point. Ptr->get. Circumference(); double area = point. Ptr->get. Area(); 30 31 return 0; 32 33 Outline } // end main These functions are only defined in Circle. However, point. Ptr is of class Point. fig 10_07. cpp (2 of 2) 2003 Prentice Hall, Inc. All rights reserved. 20
C: cpphtp 4examplesch 10fig 10_07. cpp(25) : error C 2039: 'get. Radius' : is not a member of 'Point' C: cpphtp 4examplesch 10fig 10_07point. h(6) : see declaration of 'Point' Outline C: cpphtp 4examplesch 10fig 10_07. cpp(26) : error C 2039: 'set. Radius' : is not a member of 'Point' C: cpphtp 4examplesch 10fig 10_07point. h(6) : see declaration of 'Point' C: cpphtp 4examplesch 10fig 10_07. cpp(27) : error C 2039: 'get. Diameter' : is not a member of 'Point' C: cpphtp 4examplesch 10fig 10_07point. h(6) : see declaration of 'Point' fig 10_07. cpp output (1 of 1) C: cpphtp 4examplesch 10fig 10_07. cpp(28) : error C 2039: 'get. Circumference' : is not a member of 'Point' C: cpphtp 4examplesch 10fig 10_07point. h(6) : see declaration of 'Point' C: cpphtp 4examplesch 10fig 10_07. cpp(29) : error C 2039: 'get. Area' : is not a member of 'Point' C: cpphtp 4examplesch 10fig 10_07point. h(6) : see declaration of 'Point' 2003 Prentice Hall, Inc. All rights reserved. 21
22 10. 2. 4 Virtual Functions • Typically, pointer-class determines functions • virtual functions – Object (not pointer) determines function called • Why useful? – Suppose Circle, Triangle, Rectangle derived from Shape • Each has own draw function – To draw any shape • Have base class Shape pointer, call draw • Program determines proper draw function at run time (dynamically) • Treat all shapes generically 2003 Prentice Hall, Inc. All rights reserved.
23 10. 2. 4 Virtual Functions • Declare draw as virtual in base class – Override draw in each derived class • Like redefining, but new function must have same signature – If function declared virtual, can only be overridden • virtual void draw() const; • Once declared virtual, virtual in all derived classes – Good practice to explicitly declare virtual • Dynamic binding – Choose proper function to call at run time – Only occurs off pointer handles • If function called from object, uses that object’s definition 2003 Prentice Hall, Inc. All rights reserved.
24 10. 2. 4 Virtual Functions • Example – Redo Point, Circle example with virtual functions – Base-class pointer to derived-class object • Will call derived-class function 2003 Prentice Hall, Inc. All rights reserved.
1 2 3 4 // Fig. 10. 8: point. h // Point class definition represents an x-y coordinate pair. #ifndef POINT_H #define POINT_H 5 6 class Point { 7 8 9 public: Point( int = 0, int = 0 ); // default constructor 10 11 12 13 14 15 16 17 void set. X( int ); int get. X() const; // set x in coordinate pair // return x from coordinate pair void set. Y( int ); int get. Y() const; // set y in coordinate pair will be virtual in all // return y from coordinate pair virtual void print() const; 18 19 20 21 private: int x; int y; 22 23 }; // end class Point 24 25 #endif Print declared virtual. It Outline point. h (1 of 1) derived classes. // output Point object // x part of coordinate pair // y part of coordinate pair 2003 Prentice Hall, Inc. All rights reserved. 25
1 2 3 4 // Fig. 10. 9: circle. h // Circle class contains x-y coordinate pair and radius. #ifndef CIRCLE_H #define CIRCLE_H 5 6 #include "point. h" 7 8 class Circle : public Point { 9 10 public: Outline // Point class definition 11 12 13 // default constructor Circle( int = 0, double = 0. 0 ); 14 15 16 void set. Radius( double ); double get. Radius() const; 17 18 19 20 double get. Diameter() const; double get. Circumference() const; double get. Area() const; // return diameter // return circumference // return area 21 22 virtual void print() const; // output Circle object 23 24 25 private: double radius; 26 27 }; // end class Circle 28 29 #endif circle. h (1 of 1) // set radius // return radius // Circle's radius 2003 Prentice Hall, Inc. All rights reserved. 26
1 2 3 4 // Fig. 10: fig 10_10. cpp // Introducing polymorphism, virtual functions and dynamic // binding. #include <iostream> 5 6 7 8 using std: : cout; using std: : endl; using std: : fixed; 9 10 #include <iomanip> 11 12 using std: : setprecision; 13 14 15 #include "point. h" #include "circle. h" 16 17 18 19 20 int main() { Point point( 30, 50 ); Point *point. Ptr = 0; 21 22 23 // Point class definition // Circle class definition Outline fig 10_10. cpp (1 of 3) Circle circle( 120, 89, 2. 7 ); Circle *circle. Ptr = 0; 24 2003 Prentice Hall, Inc. All rights reserved. 27
25 26 // set floating-point numeric formatting cout << fixed << setprecision( 2 ); 27 28 29 30 31 32 33 34 // output objects point and circle using static binding cout << "Invoking print function on point and circle " << "nobjects with static binding " << "nn. Point: "; point. print(); // static binding cout << "n. Circle: "; circle. print(); // static binding 35 36 37 38 // output objects point and circle using dynamic binding cout << "nn. Invoking print function on point and circle " << "nobjects with dynamic binding"; 39 40 41 42 43 44 45 // aim base-class pointer at base-class object and print point. Ptr = &point; cout << "nn. Calling virtual function print with base-class" << "npointer to base-class object" << "ninvokes base-class print function: n" ; point. Ptr->print(); Outline fig 10_10. cpp (2 of 3) 46 2003 Prentice Hall, Inc. All rights reserved. 28
47 48 49 50 51 52 53 // aim derived-class pointer at derived-class // object and print circle. Ptr = &circle; cout << "nn. Calling virtual function print with " << "nderived-class pointer to derived-class object " << "ninvokes derived-class print function: n" ; circle. Ptr->print(); 54 55 56 57 58 59 60 61 // aim base-class pointer at derived-class object and print point. Ptr = &circle; cout << "nn. Calling virtual function print with base-class" << "npointer to derived-class object " << "ninvokes derived-class print function: n" ; point. Ptr->print(); // polymorphism: invokes circle's print cout << endl; 62 63 return 0; 64 65 } // end main Outline fig 10_10. cpp (3 of 3) At run time, the program determines that point. Ptr is aiming at a Circle object, and calls Circle’s print function. This is an example of polymorphism. 2003 Prentice Hall, Inc. All rights reserved. 29
Invoking print function on point and circle objects with static binding Outline Point: [30, 50] Circle: Center = [120, 89]; Radius = 2. 70 Invoking print function on point and circle objects with dynamic binding Calling virtual function print with base-class pointer to base-class object invokes base-class print function: [30, 50] fig 10_10. cpp output (1 of 1) Calling virtual function print with derived-class pointer to derived-class object invokes derived-class print function: Center = [120, 89]; Radius = 2. 70 Calling virtual function print with base-class pointer to derived-class object invokes derived-class print function: Center = [120, 89]; Radius = 2. 70 2003 Prentice Hall, Inc. All rights reserved. 30
31 10. 2. 4 Virtual Functions • Polymorphism – Same message, “print”, given to many objects • All through a base pointer – Message takes on “many forms” • Summary – Base-pointer to base-object, derived-pointer to derived • Straightforward – Base-pointer to derived object • Can only call base-class functions – Derived-pointer to base-object • Compiler error • Allowed if explicit cast made (more in section 10. 9) 2003 Prentice Hall, Inc. All rights reserved.
32 10. 3 Polymorphism Examples • Examples – Suppose Rectangle derives from Quadrilateral • Rectangle more specific Quadrilateral • Any operation on Quadrilateral can be done on Rectangle (i. e. , perimeter, area) • Suppose designing video game – Base class Space. Object • Derived Martian, Space. Ship, Laser. Beam • Base function draw – To refresh screen • Screen manager has vector of base-class pointers to objects • Send draw message to each object • Same message has “many forms” of results 2003 Prentice Hall, Inc. All rights reserved.
33 10. 3 Polymorphism Examples • Video game example, continued – Easy to add class Mercurian • Inherits from Space. Object • Provides own definition for draw – Screen manager does not need to change code • Calls draw regardless of object’s type • Mercurian objects “plug right in” • Polymorphism – Command many objects without knowing type – Extensible programs • Add classes easily 2003 Prentice Hall, Inc. All rights reserved.
34 10. 4 Type Fields and switch Structures • One way to determine object's class – Give base class an attribute • shape. Type in class Shape – Use switch to call proper print function • Many problems – May forget to test for case in switch – If add/remove a class, must update switch structures • Time consuming and error prone • Better to use polymorphism – Less branching logic, simpler programs, less debugging 2003 Prentice Hall, Inc. All rights reserved.
35 10. 5 Abstract Classes • Abstract classes – Sole purpose: to be a base class (called abstract base classes) – Incomplete • Derived classes fill in "missing pieces" – Cannot make objects from abstract class • However, can have pointers and references • Concrete classes – Can instantiate objects – Implement all functions they define – Provide specifics 2003 Prentice Hall, Inc. All rights reserved.
36 10. 5 Abstract Classes • Abstract classes not required, but helpful • To make a class abstract – Need one or more "pure" virtual functions • Declare function with initializer of 0 virtual void draw() const = 0; – Regular virtual functions • Have implementations, overriding is optional – Pure virtual functions • No implementation, must be overridden – Abstract classes can have data and concrete functions • Required to have one or more pure virtual functions 2003 Prentice Hall, Inc. All rights reserved.
37 10. 5 Abstract Classes • Abstract base class pointers – Useful for polymorphism • Application example – Abstract class Shape • Defines draw as pure virtual function – Circle, Triangle, Rectangle derived from Shape • Each must implement draw – Screen manager knows that each object can draw itself • Iterators (more Chapter 21) – Walk through elements in vector/array – Use base-class pointer to send draw message to each 2003 Prentice Hall, Inc. All rights reserved.
10. 6 Case Study: Inheriting Interface and Implementation • Make abstract base class Shape – Pure virtual functions (must be implemented) • get. Name, print • Default implementation does not make sense – Virtual functions (may be redefined) • get. Area, get. Volume – Initially return 0. 0 • If not redefined, uses base class definition – Derive classes Point, Circle, Cylinder 2003 Prentice Hall, Inc. All rights reserved. 38
10. 6 Case Study: Inheriting Interface and Implementation get. Area get. Volume get. Name print Shape 0. 0 = 0 Point 0. 0 "Point" [x, y] Circle pr 2 0. 0 "Circle" center=[x, y]; radius=r 2 pr 2 +2 prh pr 2 h "Cylinder" center=[x, y]; radius=r; height=h Cylinder 2003 Prentice Hall, Inc. All rights reserved. 39
1 2 3 4 // Fig. 10. 12: shape. h // Shape abstract-base-class definition. #ifndef SHAPE_H #define SHAPE_H 5 6 #include <string> 7 8 using std: : string; 9 10 class Shape { 11 12 13 14 15 Outline // C++ standard string class public: Virtual and pure virtual functions. // virtual function that returns shape area virtual double get. Area() const; 16 17 18 // virtual function that returns shape volume virtual double get. Volume() const; 19 20 21 22 // pure virtual functions; overridden in derived classes virtual string get. Name() const = 0; // return shape name virtual void print() const = 0; // output shape 23 24 }; // end class Shape 25 26 #endif shape. h (1 of 1) 2003 Prentice Hall, Inc. All rights reserved. 40
1 2 3 // Fig. 10. 13: shape. cpp // Shape class member-function definitions. #include <iostream> 4 5 using std: : cout; 6 7 #include "shape. h" 8 9 10 11 12 // return area of shape; 0. 0 by default double get. Area() const { return 0. 0; 13 14 } 15 16 17 18 19 // return volume of shape; 0. 0 by default double get. Volume() const { return 0. 0; 20 21 } Outline // Shape class definition // end function get. Area shape. cpp (1 of 1) // end function get. Volume 2003 Prentice Hall, Inc. All rights reserved. 41
1 2 3 4 // Fig. 10. 14: point. h // Point class definition represents an x-y coordinate pair. #ifndef POINT_H #define POINT_H 5 6 #include "shape. h" 7 8 class Point : public Shape { 9 10 11 public: Point( int = 0, int = 0 ); // default constructor Outline // Shape class definition 12 13 14 15 16 17 18 19 20 // return name of shape (i. e. , "Point" ) virtual string get. Name() const; 21 22 virtual void print() const; Point only redefines print, since get. Area and get. Volume are pair zero (it can use the default coordinate implementation). from coordinate pair void set. X( int ); int get. X() const; // set x in coordinate pair get. Name and // return x from coordinate pair void set. Y( int ); int get. Y() const; // set y in // return y point. h (1 of 2) // output Point object 23 2003 Prentice Hall, Inc. All rights reserved. 42
24 25 26 private: int x; int y; 27 28 }; // end class Point 29 30 #endif // x part of coordinate pair // y part of coordinate pair Outline point. h (2 of 2) 2003 Prentice Hall, Inc. All rights reserved. 43
1 2 3 // Fig. 10. 15: point. cpp // Point class member-function definitions. #include <iostream> 4 5 using std: : cout; 6 7 #include "point. h" 8 9 10 11 12 13 // default constructor Point: : Point( int x. Value, int y. Value ) : x( x. Value ), y( y. Value ) { // empty body 14 15 } // end Point constructor 16 17 18 19 20 // set x in coordinate pair void Point: : set. X( int x. Value ) { x = x. Value; // no need for validation 21 22 } // end function set. X Outline // Point class definition point. cpp (1 of 3) 23 2003 Prentice Hall, Inc. All rights reserved. 44
24 25 26 27 // return x from coordinate pair int Point: : get. X() const { return x; 28 29 } // end function get. X 30 31 32 33 34 // set y in coordinate pair void Point: : set. Y( int y. Value ) { y = y. Value; // no need for validation 35 36 } // end function set. Y 37 38 39 40 41 // return y from coordinate pair int Point: : get. Y() const { return y; 42 43 } // end function get. Y Outline point. cpp (2 of 3) 44 2003 Prentice Hall, Inc. All rights reserved. 45
45 46 47 48 49 50 51 52 53 54 55 56 57 // override pure virtual function get. Name: return name of Point string Point: : get. Name() const { return "Point"; } Outline // end function get. Name // override pure virtual function print: output Point object void Point: : print() const { cout << '[' << get. X() << ", " << get. Y() << ']'; } // end function print Must override pure virtual functions get. Name and print. point. cpp (3 of 3) 2003 Prentice Hall, Inc. All rights reserved. 46
1 2 3 4 // Fig. 10. 16: circle. h // Circle class contains x-y coordinate pair and radius. #ifndef CIRCLE_H #define CIRCLE_H 5 6 #include "point. h" 7 8 class Circle : public Point { 9 10 public: Outline // Point class definition 11 12 13 // default constructor Circle( int = 0, double = 0. 0 ); 14 15 16 void set. Radius( double ); double get. Radius() const; 17 18 19 20 double get. Diameter() const; double get. Circumference() const; virtual double get. Area() const; 21 22 23 // return name of shape (i. e. , "Circle") virtual string get. Name() const; 24 25 virtual void print() const; circle. h (1 of 2) // set radius // return diameter // return circumference // return area // output Circle object 2003 Prentice Hall, Inc. All rights reserved. 47
26 27 28 private: double radius; 29 30 }; // end class Circle 31 32 #endif Outline // Circle's radius circle. h (2 of 2) 2003 Prentice Hall, Inc. All rights reserved. 48
1 2 3 // Fig. 10. 17: circle. cpp // Circle class member-function definitions. #include <iostream> 4 5 using std: : cout; 6 7 #include "circle. h" 8 9 10 11 12 13 // default constructor Circle: : Circle( int x. Value, int y. Value, double radius. Value ) : Point( x. Value, y. Value ) // call base-class constructor { set. Radius( radius. Value ); 14 15 } // end Circle constructor 16 17 18 19 20 // set radius void Circle: : set. Radius( double radius. Value ) { radius = ( radius. Value < 0. 0 ? 0. 0 : radius. Value ); 21 22 } // end function set. Radius Outline // Circle class definition circle. cpp (1 of 3) 23 2003 Prentice Hall, Inc. All rights reserved. 49
24 25 26 27 // return radius double Circle: : get. Radius() const { return radius; 28 29 } // end function get. Radius 30 31 32 33 34 // calculate and return diameter double Circle: : get. Diameter() const { return 2 * get. Radius(); 35 36 } // end function get. Diameter 37 38 39 40 41 // calculate and return circumference double Circle: : get. Circumference() const { return 3. 14159 * get. Diameter(); 42 43 } // end function get. Circumference Outline circle. cpp (2 of 3) 44 2003 Prentice Hall, Inc. All rights reserved. 50
45 46 47 48 // override virtual function get. Area: return area of Circle double Circle: : get. Area() const { return 3. 14159 * get. Radius(); 49 50 } // end function get. Area 51 52 53 54 55 Override get. Area // override virutual function get. Name: return name ofbecause Circle it string Circle: : get. Name() const now applies to Circle. { return "Circle"; 56 57 } 58 59 60 61 62 63 64 // override virtual function print: output Circle object void Circle: : print() const { cout << "center is "; Point: : print(); // invoke Point's print function cout << "; radius is " << get. Radius(); 65 66 } // end function print // end function get. Name Outline circle. cpp (3 of 3) 2003 Prentice Hall, Inc. All rights reserved. 51
1 2 3 4 // Fig. 10. 18: cylinder. h // Cylinder class inherits from class Circle. #ifndef CYLINDER_H #define CYLINDER_H 5 6 #include "circle. h" 7 8 class Cylinder : public Circle { 9 10 public: 11 12 13 14 15 16 17 18 19 20 Outline // Circle class definition // default constructor Cylinder( int = 0, double = 0. 0 ); void set. Height( double ); double get. Height() const; cylinder. h (1 of 2) // set Cylinder's height // return Cylinder's height virtual double get. Area() const; // return Cylinder's area virtual double get. Volume() const; // return Cylinder's volume 2003 Prentice Hall, Inc. All rights reserved. 52
21 22 // return name of shape (i. e. , "Cylinder" ) virtual string get. Name() const; 23 24 virtual void print() const; 25 26 27 private: double height; 28 29 }; // end class Cylinder 30 31 #endif Outline // output Cylinder // Cylinder's height cylinder. h (2 of 2) 2003 Prentice Hall, Inc. All rights reserved. 53
1 2 3 // Fig. 10. 19: cylinder. cpp // Cylinder class inherits from class Circle. #include <iostream> 4 5 using std: : cout; 6 7 #include "cylinder. h" 8 9 10 11 12 13 14 // default constructor Cylinder: : Cylinder( int x. Value, int y. Value, double radius. Value, double height. Value ) : Circle( x. Value, y. Value, radius. Value ) { set. Height( height. Value ); 15 16 } // end Cylinder constructor 17 18 19 20 21 // set Cylinder's height void Cylinder: : set. Height( double height. Value ) { height = ( height. Value < 0. 0 ? 0. 0 : height. Value ); 22 23 } // end function set. Height Outline // Cylinder class definition cylinder. cpp (1 of 3) 2003 Prentice Hall, Inc. All rights reserved. 54
24 25 26 27 28 // get Cylinder's height double Cylinder: : get. Height() const { return height; 29 30 } // end function get. Height 31 32 33 34 35 36 // override virtual function get. Area: return Cylinder area double Cylinder: : get. Area() const { return 2 * Circle: : get. Area() + // code reuse get. Circumference() * get. Height(); 37 38 } // end function get. Area 39 40 41 42 43 // override virtual function get. Volume: return Cylinder volume double Cylinder: : get. Volume() const { return Circle: : get. Area() * get. Height(); // code reuse 44 45 } // end function get. Volume Outline cylinder. cpp (2 of 3) 46 2003 Prentice Hall, Inc. All rights reserved. 55
47 48 49 50 // override virtual function get. Name: return name of Cylinder string Cylinder: : get. Name() const { return "Cylinder"; 51 52 } 53 54 55 56 57 58 // output Cylinder object void Cylinder: : print() const { Circle: : print(); // code reuse cout << "; height is " << get. Height(); 59 60 Outline // end function get. Name } // end function print cylinder. cpp (3 of 3) 2003 Prentice Hall, Inc. All rights reserved. 56
1 2 3 // Fig. 10. 20: fig 10_20. cpp // Driver for shape, point, circle, cylinder hierarchy. #include <iostream> 4 5 6 7 using std: : cout; using std: : endl; using std: : fixed; 8 9 #include <iomanip> 10 11 using std: : setprecision; 12 13 #include <vector> 14 15 using std: : vector; 16 17 18 19 20 #include 21 22 23 void virtual. Via. Pointer( const Shape * ); void virtual. Via. Reference( const Shape & ); "shape. h" "point. h" "circle. h" "cylinder. h" Outline fig 10_20. cpp (1 of 5) // // Shape class definition Point class definition Circle class definition Cylinder class definition 24 2003 Prentice Hall, Inc. All rights reserved. 57
25 26 27 28 int main() { // set floating-point number format cout << fixed << setprecision( 2 ); Outline 29 30 31 32 Point point( 7, 11 ); Circle circle( 22, 8, 3. 5 ); Cylinder cylinder( 10, 3. 3, 10 ); 33 34 35 36 cout << point. get. Name() << ": "; point. print(); cout << 'n'; // static binding 37 38 39 40 cout << circle. get. Name() << ": "; circle. print(); cout << 'n'; // static binding 41 42 43 44 cout << cylinder. get. Name() << ": "; // static binding cylinder. print(); // static binding cout << "nn"; // create a Point // create a Circle // create a Cylinder fig 10_20. cpp (2 of 5) 45 2003 Prentice Hall, Inc. All rights reserved. 58
46 47 // create vector of three base-class pointers vector< Shape * > shape. Vector( 3 ); 48 49 50 // aim shape. Vector[0] at derived-class shape. Vector[ 0 ] = &point; 51 52 53 54 55 56 Outline Create a vector of generic Shape pointers, and aim them at Point object various objects. // aim shape. Vector[1] at derived-class Circle object Function shape. Vector[ 1 ] = &circle; virtual. Via. Pointer // aim shape. Vector[2] at derived-class shape. Vector[ 2 ] = &cylinder; calls the virtual functions (print, Cylinder object get. Name, etc. ) using the baseclass pointers. 57 58 59 60 61 62 // loop through shape. Vector and call virtual. Via. Pointer The types are dynamically // to print the shape name, attributes, area and volume // of each object using dynamic binding at run-time. cout << "n. Virtual function calls made off " << "base-class pointers: nn" ; 63 64 65 for ( int i = 0; i < shape. Vector. size(); i++ ) virtual. Via. Pointer( shape. Vector[ i ] ); fig 10_20. cpp bound (3 of 5) 66 2003 Prentice Hall, Inc. All rights reserved. 59
67 68 69 70 71 // loop through shape. Vector and call virtual. Via. Reference // to print the shape name, attributes, area and volume // of each object using dynamic binding cout << "n. Virtual function calls made off " Use references instead << "base-class references: nn" ; 72 73 74 for ( int j = 0; j < shape. Vector. size(); j++ ) virtual. Via. Reference ( *shape. Vector[ j ] ); 75 76 return 0; 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 Outline of pointers, for the same effect. } // end main // make virtual function calls off a base-class pointer Call virtual functions; the // using dynamic binding proper) class function will be void virtual. Via. Pointer( const Shape *base. Class. Ptr called at run-time. { cout << base. Class. Ptr->get. Name() << ": "; fig 10_20. cpp (4 of 5) base. Class. Ptr->print(); cout << "narea is " << base. Class. Ptr->get. Area() << "nvolume is " << base. Class. Ptr->get. Volume() << "nn"; } // end function virtual. Via. Pointer 93 2003 Prentice Hall, Inc. All rights reserved. 60
94 95 96 97 98 99 100 101 102 103 104 105 // make virtual function calls off a base-class reference // using dynamic binding void virtual. Via. Reference( const Shape &base. Class. Ref ) { cout << base. Class. Ref. get. Name() << ": "; Outline base. Class. Ref. print(); cout << "narea is " << base. Class. Ref. get. Area() << "nvolume is " << base. Class. Ref. get. Volume() << "nn"; } // end function virtual. Via. Reference fig 10_20. cpp (5 of 5) 2003 Prentice Hall, Inc. All rights reserved. 61
Point: [7, 11] Circle: center is [22, 8]; radius is 3. 50 Cylinder: center is [10, 10]; radius is 3. 30; height is 10. 00 Outline Virtual function calls made off base-class pointers: Point: [7, 11] area is 0. 00 volume is 0. 00 Circle: center is [22, 8]; radius is 3. 50 area is 38. 48 volume is 0. 00 fig 10_20. cpp output (1 of 2) Cylinder: center is [10, 10]; radius is 3. 30; height is 10. 00 area is 275. 77 volume is 342. 12 2003 Prentice Hall, Inc. All rights reserved. 62
Virtual function calls made off base-class references: Outline Point: [7, 11] area is 0. 00 volume is 0. 00 Circle: center is [22, 8]; radius is 3. 50 area is 38. 48 volume is 0. 00 Cylinder: center is [10, 10]; radius is 3. 30; height is 10. 00 area is 275. 77 volume is 342. 12 fig 10_20. cpp output (2 of 2) 2003 Prentice Hall, Inc. All rights reserved. 63
10. 7 Polymorphism, Virtual Functions and Dynamic Binding “Under the Hood” • Polymorphism has overhead – Not used in STL (Standard Template Library) to optimize performance • virtual function table (vtable) – Every class with a virtual function has a vtable – For every virtual function, vtable has pointer to the proper function – If derived class has same function as base class • Function pointer aims at base-class function – Detailed explanation in Fig. 10. 21 2003 Prentice Hall, Inc. All rights reserved. 64
65 10. 8 Virtual Destructors • Base class pointer to derived object – If destroyed using delete, behavior unspecified • Simple fix – Declare base-class destructor virtual • Makes derived-class destructors virtual – Now, when delete used appropriate destructor called • When derived-class object destroyed – Derived-class destructor executes first – Base-class destructor executes afterwards • Constructors cannot be virtual 2003 Prentice Hall, Inc. All rights reserved.
10. 9 Case Study: Payroll System Using Polymorphism • Create a payroll program – Use virtual functions and polymorphism • Problem statement – 4 types of employees, paid weekly • • Salaried (fixed salary, no matter the hours) Hourly (overtime [>40 hours] pays time and a half) Commission (paid percentage of sales) Base-plus-commission (base salary + percentage of sales) – Boss wants to raise pay by 10% 2003 Prentice Hall, Inc. All rights reserved. 66
10. 9 Case Study: Payroll System Using Polymorphism • Base class Employee – Pure virtual function earnings (returns pay) • Pure virtual because need to know employee type • Cannot calculate for generic employee – Other classes derive from Employee Salaried. Employee Commission. Employee Base. Plus. Commission. Employee 2003 Prentice Hall, Inc. All rights reserved. Hourly. Employee 67
10. 9 Case Study: Payroll System Using Polymorphism • Downcasting – dynamic_cast operator • Determine object's type at runtime • Returns 0 if not of proper type (cannot be cast) New. Class *ptr = dynamic_cast < New. Class *> object. Ptr; • Keyword typeid – Header <typeinfo> – Usage: typeid(object) • Returns type_info object • Has information about type of operand, including name • typeid(object). name() 2003 Prentice Hall, Inc. All rights reserved. 68
1 2 3 4 // Fig. 10. 23: employee. h // Employee abstract base class. #ifndef EMPLOYEE_H #define EMPLOYEE_H 5 6 #include <string> 7 8 using std: : string; 9 10 class Employee { 11 12 13 public: Employee( const string &, const string & ); Outline // C++ standard string class 14 15 16 void set. First. Name( const string & ); string get. First. Name() const; 17 18 19 void set. Last. Name( const string & ); string get. Last. Name() const; 20 21 22 void set. Social. Security. Number ( const string & ); string get. Social. Security. Number () const; employee. h (1 of 2) 23 2003 Prentice Hall, Inc. All rights reserved. 69
24 25 26 // pure virtual function makes Employee abstract base class virtual double earnings() const = 0; // pure virtual void print() const; // virtual 27 28 29 30 31 private: string first. Name; string last. Name; string social. Security. Number; 32 33 }; // end class Employee 34 35 #endif // EMPLOYEE_H Outline employee. h (2 of 2) 2003 Prentice Hall, Inc. All rights reserved. 70
1 2 3 4 // Fig. 10. 24: employee. cpp // Abstract-base-class Employee member-function definitions. // Note: No definitions are given for pure virtual functions. #include <iostream> 5 6 7 using std: : cout; using std: : endl; 8 9 #include "employee. h" 10 11 12 13 14 15 16 17 18 // constructor Employee: : Employee( const string &first, const string &last, const string &SSN ) : first. Name( first ), last. Name( last ), social. Security. Number ( SSN ) { // empty body 19 20 } // end Employee constructor Outline // Employee class definition employee. cpp (1 of 3) 21 2003 Prentice Hall, Inc. All rights reserved. 71
22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 // return first name string Employee: : get. First. Name() const { return first. Name; Outline } // end function get. First. Name // return last name string Employee: : get. Last. Name() const { return last. Name; } // end function get. Last. Name employee. cpp (2 of 3) // return social security number string Employee: : get. Social. Security. Number() const { return social. Security. Number; } // end function get. Social. Security. Number // set first name void Employee: : set. First. Name( const string &first ) { first. Name = first; } // end function set. First. Name 49 2003 Prentice Hall, Inc. All rights reserved. 72
50 51 52 53 54 55 // set last name void Employee: : set. Last. Name( const string &last ) { last. Name = last; Outline } // end function set. Last. Name 56 57 58 59 60 // set social security number void Employee: : set. Social. Security. Number( const string &number ) { social. Security. Number = number; // should validate 61 62 Default } // end function set. Social. Security. Number 63 64 65 66 67 68 69 // print Employee's information void Employee: : print() const { cout << get. First. Name() << ' ' << get. Last. Name() << "nsocial security number: " << get. Social. Security. Number () << endl; 70 71 } // end function print implementation for virtual function print. employee. cpp (3 of 3) 2003 Prentice Hall, Inc. All rights reserved. 73
1 2 3 4 // Fig. 10. 25: salaried. h // Salaried. Employee class derived from Employee. #ifndef SALARIED_H #define SALARIED_H 5 6 #include "employee. h" 7 8 class Salaried. Employee : public Employee { 9 10 11 12 New functions for the public: Salaried. Employee( const string &, double = 0. 0 ); Outline // Employee class definition earnings must be overridden. print is overridden to specify that this is a salaried employee. 13 14 15 void set. Weekly. Salary( double ); double get. Weekly. Salary() const; 16 17 18 virtual double earnings() const; virtual void print() const; // "salaried employee: " 19 20 21 private: double weekly. Salary; 22 23 }; // end class Salaried. Employee 24 25 #endif // SALARIED_H class. salaried. h (1 of 1) 2003 Prentice Hall, Inc. All rights reserved. 74
1 2 3 // Fig. 10. 26: salaried. cpp // Salaried. Employee class member-function definitions. #include <iostream> 4 5 using std: : cout; 6 7 #include "salaried. h" // Salaried. Employee class definition 8 9 10 11 12 13 14 15 // Salaried. Employee constructor base class constructor Salaried. Employee: : Salaried. Employee( Use const string &first, basic fields. const string &last, const string &social. Security. Number, double salary ) : Employee( first, last, social. Security. Number ) { set. Weekly. Salary( salary ); 16 17 } // end Salaried. Employee constructor 18 19 20 21 22 // set salaried employee's salary void Salaried. Employee: : set. Weekly. Salary( double salary ) { weekly. Salary = salary < 0. 0 ? 0. 0 : salary; 23 24 } // end function set. Weekly. Salary Outline for salaried. cpp (1 of 2) 25 2003 Prentice Hall, Inc. All rights reserved. 75
26 27 28 29 // calculate salaried employee's pay double Salaried. Employee: : earnings() const { return get. Weekly. Salary(); 30 31 } // end function earnings 32 33 34 35 36 // return salaried employee's salary double Salaried. Employee: : get. Weekly. Salary() const { return weekly. Salary; 37 38 } // end function get. Weekly. Salary 39 40 41 42 43 44 // print salaried employee's name void Salaried. Employee: : print() const { cout << "nsalaried employee: "; Employee: : print(); // code reuse 45 46 } // end function print Outline Must implement pure virtual functions. salaried. cpp (2 of 2) 2003 Prentice Hall, Inc. All rights reserved. 76
1 2 3 4 // Fig. 10. 27: hourly. h // Hourly. Employee class definition. #ifndef HOURLY_H #define HOURLY_H 5 6 #include "employee. h" 7 8 class Hourly. Employee : public Employee { 9 10 11 12 13 14 15 Outline // Employee class definition public: Hourly. Employee( const string &, double = 0. 0 ); void set. Wage( double ); double get. Wage() const; 16 17 18 void set. Hours( double ); double get. Hours() const; 19 20 21 virtual double earnings() const; virtual void print() const; 22 23 24 25 private: double wage; double hours; 26 27 }; // end class Hourly. Employee 28 29 #endif // HOURLY_H hourly. h (1 of 1) // wage per hour // hours worked for week 2003 Prentice Hall, Inc. All rights reserved. 77
1 2 3 // Fig. 10. 28: hourly. cpp // Hourly. Employee class member-function definitions. #include <iostream> 4 5 using std: : cout; 6 7 #include "hourly. h" 8 9 10 11 12 13 14 15 16 // constructor for class Hourly. Employee: : Hourly. Employee( const string &first, const string &last, const string &social. Security. Number, double hourly. Wage, double hours. Worked ) : Employee( first, last, social. Security. Number ) { set. Wage( hourly. Wage ); set. Hours( hours. Worked ); 17 18 } // end Hourly. Employee constructor 19 20 21 22 23 // set hourly employee's wage void Hourly. Employee: : set. Wage( double wage. Amount ) { wage = wage. Amount < 0. 0 ? 0. 0 : wage. Amount; 24 25 } // end function set. Wage Outline hourly. cpp (1 of 3) 2003 Prentice Hall, Inc. All rights reserved. 78
26 27 28 29 30 31 // set hourly employee's hours worked void Hourly. Employee: : set. Hours( double hours. Worked ) { hours = ( hours. Worked >= 0. 0 && hours. Worked <= 168. 0 ) ? hours. Worked : 0. 0; 32 33 } // end function set. Hours 34 35 36 37 38 // return hours worked double Hourly. Employee: : get. Hours() const { return hours; 39 40 } // end function get. Hours 41 42 43 44 45 // return wage double Hourly. Employee: : get. Wage() const { return wage; 46 47 } // end function get. Wage Outline hourly. cpp (2 of 3) 48 2003 Prentice Hall, Inc. All rights reserved. 79
49 50 51 52 53 54 55 // get hourly employee's pay double Hourly. Employee: : earnings() const { if ( hours <= 40 ) // no overtime return wage * hours; else // overtime is paid at wage * 1. 5 return 40 * wage + ( hours - 40 ) * wage * 1. 5; 56 57 } // end function earnings 58 59 60 61 62 63 // print hourly employee's information void Hourly. Employee: : print() const { cout << "nhourly employee: "; Employee: : print(); // code reuse 64 65 } // end function print Outline hourly. cpp (3 of 3) 2003 Prentice Hall, Inc. All rights reserved. 80
1 2 3 4 // Fig. 10. 29: commission. h // Commission. Employee class derived from Employee. #ifndef COMMISSION_H #define COMMISSION_H 5 6 #include "employee. h" 7 8 class Commission. Employee : public Employee { 9 10 11 12 public: Must set rate and&, sales. Commission. Employee( const string &, double = 0. 0 ); // Employee class definition 13 14 15 void set. Commission. Rate( double ); double get. Commission. Rate() const; 16 17 18 void set. Gross. Sales( double ); double get. Gross. Sales() const; 19 20 21 virtual double earnings() const; virtual void print() const; 22 23 24 25 private: double gross. Sales; double commission. Rate; 26 27 }; // end class Commission. Employee 28 29 #endif // COMMISSION_H Outline commission. h (1 of 1) // gross weekly sales // commission percentage 2003 Prentice Hall, Inc. All rights reserved. 81
1 2 3 // Fig. 10. 30: commission. cpp // Commission. Employee class member-function definitions. #include <iostream> 4 5 using std: : cout; 6 7 #include "commission. h" 8 9 10 11 12 13 14 15 16 // Commission. Employee constructor Commission. Employee: : Commission. Employee( const string &first, const string &last, const string &social. Security. Number, double gross. Weekly. Sales, double percent ) : Employee( first, last, social. Security. Number ) { set. Gross. Sales( gross. Weekly. Sales ); set. Commission. Rate( percent ); 17 18 } // end Commission. Employee constructor 19 20 21 22 23 // return commission employee's rate double Commission. Employee: : get. Commission. Rate() const { return commission. Rate; 24 25 } // end function get. Commission. Rate Outline // Commission class commission. cpp (1 of 3) 2003 Prentice Hall, Inc. All rights reserved. 82
26 27 28 29 30 // return commission employee's gross sales amount double Commission. Employee: : get. Gross. Sales() const { return gross. Sales; 31 32 } // end function get. Gross. Sales 33 34 35 36 37 // set commission employee's weekly base salary void Commission. Employee: : set. Gross. Sales( double sales ) { gross. Sales = sales < 0. 0 ? 0. 0 : sales; 38 39 } // end function set. Gross. Sales 40 41 42 43 44 // set commission employee's commission void Commission. Employee: : set. Commission. Rate( double rate ) { commission. Rate = ( rate > 0. 0 && rate < 1. 0 ) ? rate : 0. 0; 45 46 } // end function set. Commission. Rate Outline commission. cpp (2 of 3) 47 2003 Prentice Hall, Inc. All rights reserved. 83
48 49 50 51 // calculate commission employee's earnings double Commission. Employee: : earnings() const { return get. Commission. Rate() * get. Gross. Sales(); 52 53 } // end function earnings 54 55 56 57 58 59 // print commission employee's name void Commission. Employee: : print() const { cout << "ncommission employee: "; Employee: : print(); // code reuse 60 61 } // end function print Outline commission. cpp (3 of 3) 2003 Prentice Hall, Inc. All rights reserved. 84
1 2 3 4 5 6 // Fig. 10. 31: baseplus. h // Base. Plus. Commission. Employee class derived from Employee. Inherits from #ifndef BASEPLUS_H Commission. Employee #define BASEPLUS_H (and from Employee #include "commission. h" indirectly). // Employee class definition 7 8 class Base. Plus. Commission. Employee : public Commission. Employee { 9 10 11 12 public: Base. Plus. Commission. Employee ( const string &, double = 0. 0, double = 0. 0 ); 13 14 15 16 17 18 Outline void set. Base. Salary( double ); double get. Base. Salary() const; baseplus. h (1 of 1) virtual double earnings() const; virtual void print() const; 19 20 21 private: double base. Salary; 22 23 }; // end class Base. Plus. Commission. Employee 24 25 #endif // BASEPLUS_H // base salary per week 2003 Prentice Hall, Inc. All rights reserved. 85
1 2 3 // Fig. 10. 32: baseplus. cpp // Base. Plus. Commission. Employee member-function definitions. #include <iostream> 4 5 using std: : cout; 6 7 #include "baseplus. h" 8 9 10 11 12 13 14 15 16 17 18 // constructor for class Base. Plus. Commission. Employee : : Base. Plus. Commission. Employee ( const string &first, const string &last, const string &social. Security. Number, double gross. Sales. Amount, double rate, double base. Salary. Amount ) : Commission. Employee( first, last, social. Security. Number, gross. Sales. Amount, rate ) { set. Base. Salary( base. Salary. Amount ); 19 20 } // end Base. Plus. Commission. Employee constructor 21 22 23 24 25 // set base-salaried commission employee's wage void Base. Plus. Commission. Employee : : set. Base. Salary( double salary ) { base. Salary = salary < 0. 0 ? 0. 0 : salary; 26 27 } // end function set. Base. Salary Outline baseplus. cpp (1 of 2) 2003 Prentice Hall, Inc. All rights reserved. 86
28 29 30 31 32 // return base-salaried commission employee's base salary double Base. Plus. Commission. Employee : : get. Base. Salary() const { return base. Salary; 33 34 } // end function get. Base. Salary 35 36 37 38 39 // return base-salaried commission employee's earnings double Base. Plus. Commission. Employee : : earnings() const { return get. Base. Salary() + Commission. Employee: : earnings(); 40 41 } // end function earnings 42 43 44 45 46 47 // print base-salaried commission employee's name void Base. Plus. Commission. Employee : : print() const { cout << "nbase-salaried commission employee: " ; Employee: : print(); // code reuse 48 49 } // end function print Outline baseplus. cpp (2 of 2) 2003 Prentice Hall, Inc. All rights reserved. 87
1 2 3 // Fig. 10. 33: fig 10_33. cpp // Driver for Employee hierarchy. #include <iostream> 4 5 6 7 using std: : cout; using std: : endl; using std: : fixed; 8 9 #include <iomanip> 10 11 12 13 Outline using std: : setprecision; fig 10_33. cpp (1 of 4) #include <vector> 14 15 using std: : vector; 16 17 #include <typeinfo> 18 19 20 21 22 23 #include #include "employee. h" "salaried. h" "commission. h" "baseplus. h" "hourly. h" // // // Employee base class Salaried. Employee class Commission. Employee class Base. Plus. Commission. Employee class Hourly. Employee class 24 2003 Prentice Hall, Inc. All rights reserved. 88
25 26 27 28 int main() { // set floating-point output formatting cout << fixed << setprecision( 2 ); 29 30 31 // create vector employees vector < Employee * > employees( 4 ); 32 33 34 35 36 37 38 39 40 41 // initialize vector with Employees employees[ 0 ] = new Salaried. Employee( "John", "Smith", "111 -11 -1111", 800. 00 ); employees[ 1 ] = new Commission. Employee( "Sue", "Jones", "222 -22 -2222", 10000, . 06 ); employees[ 2 ] = new Base. Plus. Commission. Employee ( "Bob", "Lewis", "333 -33 -3333", 300, 5000, . 04 ); employees[ 3 ] = new Hourly. Employee( "Karen", "Price", "444 -44 -4444", 16. 75, 40 ); Outline fig 10_33. cpp (2 of 4) 42 2003 Prentice Hall, Inc. All rights reserved. 89
43 44 // generically process each element in vector employees to for ( int i = 0; i < employees. size(); Use i++ downcasting ) { Outline cast the employee object into a Base. Plus. Commission. Employee. If it points to the correct type of object, the pointer is non-zero. This way, we can give a raise to only Base. Plus. Commission. Employees. 45 46 47 // output employee information employees[ i ]->print(); 48 49 50 51 52 // downcast pointer Base. Plus. Commission. Employee *commission. Ptr = dynamic_cast < Base. Plus. Commission. Employee * > ( employees[ i ] ); 53 54 55 56 57 58 59 60 61 62 // determine whether element points to base-salaried // commission employee if ( commission. Ptr != 0 ) { cout << "old base salary: $" << commission. Ptr->get. Base. Salary() << endl; commission. Ptr->set. Base. Salary( 1. 10 * commission. Ptr->get. Base. Salary() ); cout << "new base salary with 10% increase is: $" << commission. Ptr->get. Base. Salary() << endl; 63 64 65 66 67 68 69 fig 10_33. cpp (3 of 4) } // end if cout << "earned $" << employees[ i ]->earnings() << endl; } // end for 2003 Prentice Hall, Inc. All rights reserved. 90
70 71 // release memory held by vector employees for ( int j = 0; j < employees. size(); j++ ) { 72 73 74 75 // output class name cout << "ndeleting object of " << typeid( *employees[ j ] ). name(); 76 77 delete employees[ j ]; 78 79 } // end for 80 81 cout << endl; 82 83 84 85 return 0; typeid returns a type_info object. This object contains information about the operand, including its name. Outline fig 10_33. cpp (4 of 4) } // end main 2003 Prentice Hall, Inc. All rights reserved. 91
salaried employee: John Smith social security number: 111 -11 -1111 earned $800. 00 Outline commission employee: Sue Jones social security number: 222 -22 -2222 earned $600. 00 base-salaried commission employee: Bob Lewis social security number: 333 -33 -3333 old base salary: $300. 00 new base salary with 10% increase is: $330. 00 earned $530. 00 fig 10_33. cpp output (1 of 1) hourly employee: Karen Price social security number: 444 -44 -4444 earned $670. 00 deleting object of of class Salaried. Employee Commission. Employee Base. Plus. Commission. Employee Hourly. Employee 2003 Prentice Hall, Inc. All rights reserved. 92
- Slides: 92