1 / 41

CS342 Data Structure

CS342 Data Structure. Review of C++: Overriding base-class functions. Overriding Base-Class Members in a Derived Class. To override a base-class member function In the derived class, supply a new version of that function with the same signature same function name, different definition

Télécharger la présentation

CS342 Data Structure

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. CS342 Data Structure Review of C++: Overriding base-class functions

  2. Overriding Base-Class Members in a Derived Class • To override a base-class member function • In the derived class, supply a new version of that function with the same signature • same function name, different definition • When the function is then mentioned by name in the derived class, the derived version is automatically called • The scope-resolution operator may be used to access the base class version from the derived class

  3. 1 // Fig. 9.5: employ.h 17 // Fig. 9.5: employ.cpp 2 // Definition of class Employee 18 // Member function definitions for class Employee 19 #include <iostream> 3 #ifndef EMPLOY_H 4 #define EMPLOY_H 20 21 using std::cout; 5 6 class Employee { 22 23 #include <cstring> 7 public: 24 #include <cassert> 8 Employee( const char *, const char * ); // constructor 9 void print() const; // output first and last name 25 #include "employ.h" 26 10 ~Employee(); // destructor 11 private: 27 // Constructor dynamically allocates space for the 28 // first and last name and uses strcpy to copy 12 char *firstName; // dynamically allocated string 13 char *lastName; // dynamically allocated string 29 // the first and last names into the object. 14 }; 30 Employee::Employee( const char *first, const char *last ) 15 31 { 16 #endif 32 firstName = new char[ strlen( first ) + 1 ]; 1. Employee class definition ----------------------- 1. Load header 1.1 Function definitions

  4. 33 assert( firstName != 0 ); // terminate if not allocated 51 // Fig. 9.5: hourly.h 34 strcpy( firstName, first ); 52 // Definition of class HourlyWorker 53 #ifndef HOURLY_H 35 54 #define HOURLY_H 36 lastName = new char[ strlen( last ) + 1 ]; 55 37 assert( lastName != 0 ); // terminate if not allocated 56 #include "employ.h" 38 strcpy( lastName, last ); 39 } 57 HourlyWorker inherits from Employee. 58 class HourlyWorker : public Employee { 40 59 public: 41 // Output employee name HourlyWorker will override the print function. 60 HourlyWorker( const char*, const char*, double, double ); 42 void Employee::print() const 61 double getPay() const; // calculate and return salary 43 { cout << firstName << ' ' << lastName; } 44 62 void print() const; // overridden base-class print 63 private: 45 // Destructor deallocates dynamically allocated memory 46 Employee::~Employee() 47 { 48 delete [] firstName; // reclaim dynamic memory 49 delete [] lastName; // reclaim dynamic memory 50 } 1.1 Function definitions --------------------- 1. HourlyWorker class definition

  5. 64 double wage; // wage per hour 69 // Fig. 9.5: hourly.cpp 65 double hours; // hours worked for week 70 // Member function definitions for class HourlyWorker 66 }; 71 #include <iostream> 67 72 68 #endif 73 using std::cout; 74 using std::endl; 75 76 #include <iomanip> 77 78 using std::ios; 79 using std::setiosflags; 80 using std::setprecision; 81 82 #include "hourly.h" 83 84 // Constructor for class HourlyWorker 85 HourlyWorker::HourlyWorker( const char *first, 86 const char *last, 87 double initHours, double initWage ) 88 : Employee( first, last ) // call base-class constructor 89 { 90 hours = initHours; // should validate 91 wage = initWage; // should validate 92 } 93 94 // Get the HourlyWorker's pay 95 double HourlyWorker::getPay() const { return wage * hours; } 1. Load header 1.1 Function definitions

  6. 107 // Fig. 9.5: fig09_05.cpp 96 97 // Print the HourlyWorker's name and pay 108 // Overriding a base-class member function in a 98 void HourlyWorker::print() const 109 // derived class. 99 { 110 #include "hourly.h" 100 cout << "HourlyWorker::print() is executing\n\n"; 111 The print function is overriden in HourlyWorker. However, the new function still can call the original print function using :: 112 int main() 101 Employee::print(); // call base-class print function 102 113 { 103 cout << " is an hourly worker with pay of $" 114 HourlyWorker h( "Bob", "Smith", 40.0, 10.00 ); 104 << setiosflags( ios::fixed | ios::showpoint ) 115 h.print(); 116 return 0; 105 << setprecision( 2 ) << getPay() << endl; 106 } 117 } 1.1 Function Definitions -------------------- 1. Load header 1.1 Initialize object 2. Function call Program Output HourlyWorker::print() is executing Bob Smith is an hourly worker with pay of $400.00

  7. Implicit Derived-Class Object to Base-Class Object Conversion • Assignment of derived and base classes • Derived-class type and base-class type are different • Derived-class object can be treated as a base-class object • Derived class has members corresponding to all of the base class’s members • Derived-class has more members than the base-class object • Derived-class object canbe assigned to a base-class object • Base-class object cannot be treated as a derived-class object • Would leave additional derived class members undefined • Base-class object cannotbe assigned to a derived class object unless the assignment operator is overloaded to allow such an assignment

  8. Implicit Derived-Class Object to Base-Class Object Conversion continued • Mixing base and derived class pointers and objects • Referring to a base-class object with a base-class pointer • Allowed • Referring to a derived-class object with a derived-class pointer • Allowed • Referring to a derived-class object with a base-class pointer • Possible syntax error • Code can only refer to base-class members, or syntax error • Referring to a base-class object with a derived-class pointer • Syntax error, unless • The derived-class pointer must first be cast to a base-class pointer

  9. Down-casting Base-Class Pointers to Derived Class Pointers • Derived classes relationships to base classes • Objects of a derived class can be treated as objects of the base class • Reverse not true — base class objects cannot be derived-class objects • Down-casting a pointer • Use an explicit cast to convert a base-class pointer to a derived-class pointer • If pointer is going to be de-referenced, the type of the pointer must match the type of object to which the pointer points • Format: derivedPtr = static_cast< DerivedClass * > basePtr;

  10. Down-casting Base-Class Pointers to Derived-Class Pointers continued • The following example: point (base class)  circle (derived class) • Demonstrates the down-casting of base class pointers to derived class pointers • Class Circle is derived from class Point • A pointer of type Point is used to reference a Circle object, and a pointer to type Circle is used to reference a Point object

  11. Example highlight: point (base) class and circle (derived) class pointPtr = &c; // Assign address of circle object to pointPtr is OK! // Treat a circle as a point (see only the point base class part) // i.e., *pointPtr refers to the point (base class) object. circlePtr = &p; // Assign address of a point object to a circlePtr is not allowed circlePtr = static_cast< Circle * >( pointPtr ); // if pointPtr = &c; then // *circlePtr refers to the circle object! pointPtr = &p; // Assign address of point object to pointPtr is OK. circlePtr = static_cast< Circle * >( pointPtr ); // here *circlePtr refers to a // circle (derived class) object, however, the data members // defined in the circle class are undefined!!! Full example follows

  12. 1 // Fig. 9.4: point.h 22 // Fig. 9.4: point.cpp 23 // Member functions for class Point 2 // Definition of class Point 24 #include <iostream> 3 #ifndef POINT_H 25 #include "point.h" 4 #define POINT_H 26 5 27 // Constructor for class Point 6 #include <iostream> 28 Point::Point( int a, int b ) { setPoint( a, b ); } 7 29 8 using std::ostream; 30 // Set x and y coordinates of Point 9 31 void Point::setPoint( int a, int b ) 10 class Point { 32 { 11 friend ostream &operator<<( ostream &, const Point & ); 33 x = a; 12 public: 13 Point( int = 0, int = 0 ); // default constructor 14 void setPoint( int, int ); // set coordinates 15 int getX() const { return x; } // get x coordinate 16 int getY() const { return y; } // get y coordinate 17 protected:// accessible by derived classes 18 int x, y; // x and y coordinates of the Point 19 }; 20 21 #endif 1. Point class definition ------------- 1. Load header 1.1 Function definitions

  13. 34 y = b; 44 // Fig. 9.4: circle.h 35 } 45 // Definition of class Circle 36 46 #ifndef CIRCLE_H 37 // Output Point (with overloaded stream insertion operator) 47 #define CIRCLE_H 38 ostream &operator<<( ostream &output, const Point &p ) 48 49 #include <iostream> 39 { 40 output << '[' << p.x << ", " << p.y << ']'; 50 Class Circle publicly inherits from class Point, so it will have class Point's public and protected member functions and data. 51 using std::ostream; 41 42 return output; // enables cascaded calls 52 43 } 53 #include <iomanip> 54 55 using std::ios; 56 using std::setiosflags; 57 using std::setprecision; 58 59 #include "point.h" 60 61 class Circle : public Point { // Circle inherits from Point 62 friend ostream &operator<<( ostream &, const Circle & ); 63 public: 64 // default constructor 1.1 Function definitions --------------------- 1. Circle class definition

  14. 65 Circle( double r = 0.0, int x = 0, int y = 0 ); 75 // Fig. 9.4: circle.cpp 76 // Member function definitions for class Circle 66 67 void setRadius( double ); // set radius 77 #include "circle.h" 68 double getRadius() const; // return radius 78 69 double area() const; // calculate area 79 // Constructor for Circle calls constructor for Point 70 protected: 80 // with a member initializer then initializes radius. Circle inherits from Point, and has Point's data members (which are set by calling Point's constructor). 71 double radius; 81 Circle::Circle( double r, int a, int b ) 72 }; 82 : Point( a, b ) // call base-class constructor 73 83 { setRadius( r ); } 74 #endif 84 85 // Set radius of Circle 86 void Circle::setRadius( double r ) 87 { radius = ( r >= 0 ? r : 0 ); } 88 1. Circle definition -------------------- 1. Load header 1.1 Function Definitions

  15. 107 // Fig. 9.4: fig09_04.cpp 89 // Get radius of Circle 90 double Circle::getRadius() const { return radius; } 108 // Casting base-class pointers to derived-class pointers 91 109 #include <iostream> 92 // Calculate area of Circle 110 111 using std::cout; 93 double Circle::area() const 94 { return 3.14159 * radius * radius; } 112 using std::endl; 113 95 96 // Output a Circle in the form: 114 #include <iomanip> 97 // Center = [x, y]; Radius = #.## 115 116 #include "point.h" 98 ostream &operator<<( ostream &output, const Circle &c ) 117 #include "circle.h" 99 { 118 100 output << "Center = " << static_cast< Point >( c ) 119 int main() 101 << "; Radius = " 102 << setiosflags( ios::fixed | ios::showpoint ) 120 { 103 << setprecision( 2 ) << c.radius; 121 Point *pointPtr = 0, p( 30, 50 ); 104 105 return output; // enables cascaded calls 106 } 1. 1 Function Definitions ---------------------- Driver 1. Load headers 1.1 Initialize objects

  16. 122 Circle *circlePtr = 0, c( 2.7, 120, 89 ); 134 cout << "\nCircle c (via *circlePtr):\n" << *circlePtr 123 135 << "\nArea of c (via circlePtr): " 136 << circlePtr->area() << '\n'; 124 cout << "Point p: " << p << "\nCircle c: " << c << '\n'; 125 137 Assign pointPtr to a Point object. It has no derived-class information. When it is cast to a Circle *, circlePtr is really assigned to a base-class object with no derived-class information. This is dangerous. 126 // Treat a Circle as a Point (see only the base class part) 138 // DANGEROUS: Treat a Point as a Circle 127 pointPtr = &c; // assign address of Circle to pointPtr 139 pointPtr = &p; // assign address of Point to pointPtr Assign derived-class pointer (&c) to base class pointer pointPtr. The base class pointer only "sees" the base-class part of the object it points to. 140 128 cout << "\nCircle c (via *pointPtr): " 141 // cast base-class pointer to derived-class pointer 129 << *pointPtr << '\n'; 142 circlePtr = static_cast< Circle * >( pointPtr ); 130 Cast pointPtr into a Circle *, and assign to circlePtr. circlePtr will treat c (the object to which it points) as a Circle. 143 cout << "\nPoint p (via *circlePtr):\n" << *circlePtr 131 // Treat a Circle as a Circle (with some casting) 144 << "\nArea of object circlePtr points to: " 132 // cast base-class pointer to derived-class pointer 145 << circlePtr->area() << endl; 133 circlePtr = static_cast< Circle * >( pointPtr ); 146 return 0; 147 } Point p: [30, 50] Circle c: Center = [120, 89]; Radius = 2.70 Circle c (via *pointPtr): [120, 89] Circle c (via *circlePtr): Center = [120, 89]; Radius = 2.70 Area of c (via circlePtr): 22.90 1.1 Initialize objects 1.2 Assign objects 2. Function calls Point p (via *circlePtr): Center = [30, 50]; Radius = 0.00 Area of object circlePtr points to: 0.00

  17. Point p: [30, 50] Circle c: Center = [120, 89]; Radius = 2.70 Circle c (via *pointPtr): [120, 89] Circle c (via *circlePtr): Center = [120, 89]; Radius = 2.70 Area of c (via circlePtr): 22.90 Point p (via *circlePtr): Center = [30, 50]; Radius = 0.00 Area of object circlePtr points to: 0.00 Program Output

  18. Virtual Functions • virtual functions • Suppose a set of shape classes such as Circle, Triangle, etc. • Every shape has own unique draw function but possible to call them by calling the draw function of base class Shape • Compiler determines dynamically (i.e., at run time) which to call • In base-class declare draw to be virtual • Override draw in each of the derived classes • virtual declaration: • Keyword virtual before function prototype in base-class virtual void draw() const; • A base-class pointer to a derived class object will call the correct draw function ShapePtr->draw(); • If a derived class does not define a virtual function, the function is inherited from the base class

  19. Virtual Functions ShapePtr->Draw(); • Compiler implements dynamic binding • Function determined during execution time ShapeObject.Draw(); • Compiler implements static binding • Function determined during compile-time

  20. Abstract and Concrete Classes • Abstract classes • Sole purpose is to provide a base class for other classes • No objects of an abstract base class can be instantiated • Too generic to define real objects (i.e., TwoDimensionalShape) • Can have pointers and references • Concrete classes • Classes that can instantiate objects • Provide specifics to make real objects (i.e., Square, Circle) • Making abstract classes • Declare one or more virtual functions as “pure” by initializing the function to zero • Example of a pure virtual function: virtual double earnings() const = 0;

  21. Polymorphism • Polymorphism • Ability for objects of different classes to respond differently to the same function call • Implemented through virtual functions • Base-class pointer (or reference) calls a virtual function • C++ chooses the correct overridden function in object • If non-virtual member function defined in multiple classes and called from base-class pointer then the base-class version is used • If called from derived-class pointer then derived-class version is used • Suppose print is not a virtual function Employee e, *ePtr = &e;HourlyWorker h, *hPtr = &h;ePtr->print(); // call base-class print functionhPtr->print(); // call derived-class print functionePtr=&h; // allowable implicit conversionePtr->print(); // still calls base-class print

  22. New Classes and Dynamic Binding • Polymorphism and virtual functions • Work well when all classes are not known in advance • Use dynamic binding to accommodate new classes being added to a system • Dynamic binding (late binding) • Object's type need not be know at compile time for a virtual function • virtual function call is matched at run time

  23. An example // Drozdek example p20 #include <iostream.h> class c1{ public: virtual void f( ){cout << "F( ) in c1\n";} void g( ){cout << "G( ) in c1\n";} }; class c2{ public: virtual void f( ){cout << "F( ) in c2\n";} void g( ){cout << "G( ) in c2\n";} }; class c3{ public: virtual void f( ){cout << "F( ) in c3\n";} };

  24. Example continued void main() { c1 o1, *p; c2 o2; c3 o3; p = &o1; p -> f(); // f in c1 p -> g(); // g in c1 p = (c1 *)&o2; // casting: old style; new style: p = static_cast< c1 * >( &o2 ); p -> f(); // f in c2 since g is virtual: dynamic binding on c2 obj p -> g(); // g in c1 since g is not virtual: static binding on p p = (c1 *)&o3; p -> f(); // f in c3 since g is virtual: dynamic binding on c3 obj p -> g(); // g in c1 since c3 has no definition for g }

  25. Case Study: A Payroll System Using Polymorphism • The following example is a payroll system • Uses virtual functions and polymorphism to perform payroll calculations based on the type of an employee

  26. 1 // Fig. 10.1: employ2.h 2 // Abstract base class Employee 3 #ifndef EMPLOY2_H 4 #define EMPLOY2_H 5 6 class Employee { earnings is declared pure virtual because the implementation will depend on which derived class it will be used in. Employee is an abstract base class. 7 public: 8 Employee( const char *, const char * ); 9 ~Employee(); // destructor reclaims memory 10 const char *getFirstName() const; 11 const char *getLastName() const; 12 13 // Pure virtual function makes Employee abstract base class 14 virtual double earnings() const = 0; // pure virtual 15 virtual void print() const; // virtual 16 private: 17 char *firstName; 18 char *lastName; 19 }; 20 21 #endif 1. Employee Definition (base class)

  27. 22 // Fig. 10.1: employ2.cpp 23 // Member function definitions for 24 // abstract base class Employee. 25 // Note: No definitions given for pure virtual functions. 26 #include <iostream> 27 28 using std::cout; 29 30 #include <cstring> 31 #include <cassert> 32 #include "employ2.h" 33 34 // Constructor dynamically allocates space for the 35 // first and last name and uses strcpy to copy 36 // the first and last names into the object. 37 Employee::Employee( const char *first, const char *last ) 38 { 39 firstName = new char[ strlen( first ) + 1 ]; 40 assert( firstName != 0 ); // test that new worked 41 strcpy( firstName, first ); 42 43 lastName = new char[ strlen( last ) + 1 ]; 44 assert( lastName != 0 ); // test that new worked 45 strcpy( lastName, last ); 46 } 47 48 // Destructor deallocates dynamically allocated memory 49 Employee::~Employee() 50 { 51 delete [] firstName; 52 delete [] lastName; 53 } 1.1 Function Definitions

  28. 54 55 // Return a pointer to the first name 56 // Const return type prevents caller from modifying private 57 // data. Caller should copy returned string before destructor 58 // deletes dynamic storage to prevent undefined pointer. 59 const char *Employee::getFirstName() const 60 { 61 return firstName; // caller must delete memory 62 } 63 64 // Return a pointer to the last name 65 // Const return type prevents caller from modifying private 66 // data. Caller should copy returned string before destructor 67 // deletes dynamic storage to prevent undefined pointer. 68 const char *Employee::getLastName() const 69 { 70 return lastName; // caller must delete memory 71 } 72 73 // Print the name of the Employee 74 void Employee::print() const 75 { cout << firstName << ' ' << lastName; } 1.1 Function Definitions

  29. 76 // Fig. 10.1: boss1.h 77 // Boss class derived from Employee 78 #ifndef BOSS1_H 79 #define BOSS1_H 80 #include "employ2.h" 81 82 class Boss : public Employee { 83 public: 84 Boss( const char *, const char *, double = 0.0 ); 85 void setWeeklySalary( double ); 86 virtual double earnings() const; 87 virtual void print() const; 88 private: 89 double weeklySalary; 90 }; 91 92 #endif 1. Boss Definition (derived class)

  30. 93 // Fig. 10.1: boss1.cpp 94 // Member function definitions for class Boss 95 #include <iostream> 96 97 using std::cout; 98 99 #include "boss1.h" Notice the overriden earnings and print functions. They were declared virtual in the base class. 100 101 // Constructor function for class Boss 102 Boss::Boss( const char *first, const char *last, double s ) 103 : Employee( first, last ) // call base-class constructor 104 { setWeeklySalary( s ); } 105 106 // Set the Boss's salary 107 void Boss::setWeeklySalary( double s ) 108 { weeklySalary = s > 0 ? s : 0; } 109 110 // Get the Boss's pay 111 double Boss::earnings() const { return weeklySalary; } 112 113 // Print the Boss's name 114 void Boss::print() const 115 { 116 cout << "\n Boss: "; 117 Employee::print(); 118 } 1.1 Function Definitions

  31. 119 // Fig. 10.1: commis1.h 120 // CommissionWorker class derived from Employee 121 #ifndef COMMIS1_H 122 #define COMMIS1_H 123 #include "employ2.h" 124 125 class CommissionWorker : public Employee { 126 public: 127 CommissionWorker( const char *, const char *, 128 double = 0.0, double = 0.0, 129 int = 0 ); 130 void setSalary( double ); 131 void setCommission( double ); 132 void setQuantity( int ); 133 virtualdouble earnings() const; 134 virtualvoid print() const; 135 private: 136 double salary; // base salary per week 137 double commission; // amount per item sold 138 int quantity; // total items sold for week 139 }; 140 141 #endif 1. CommissionWorker Definition (derived class)

  32. 142 // Fig. 10.1: commis1.cpp 143 // Member function definitions for class CommissionWorker 144 #include <iostream> 145 146 using std::cout; 147 148 #include "commis1.h" 149 150 // Constructor for class CommissionWorker 151 CommissionWorker::CommissionWorker( const char *first, 152 const char *last, double s, double c, int q ) 153 : Employee( first, last ) // call base-class constructor 154 { 155 setSalary( s ); 156 setCommission( c ); 157 setQuantity( q ); 158 } 159 160 // Set CommissionWorker's weekly base salary 161 void CommissionWorker::setSalary( double s ) 162 { salary = s > 0 ? s : 0; } 1.1 Function Definitions

  33. 163 164 // Set CommissionWorker's commission 165 void CommissionWorker::setCommission( double c ) 166 { commission = c > 0 ? c : 0; } 167 168 // Set CommissionWorker's quantity sold 169 void CommissionWorker::setQuantity( int q ) Notice the overriden earnings and print functions. They were declared virtual in the base class. 170 { quantity = q > 0 ? q : 0; } 171 172 // Determine CommissionWorker's earnings 173 double CommissionWorker::earnings() const 174 { return salary + commission * quantity; } 175 176 // Print the CommissionWorker's name 177 void CommissionWorker::print() const 178 { 179 cout << "\nCommission worker: "; 180 Employee::print(); 181 } 1.1 Function Definitions

  34. 182 // Fig. 10.1: piece1.h 183 // PieceWorker class derived from Employee 184 #ifndef PIECE1_H 185 #define PIECE1_H 186 #include "employ2.h" 187 188 class PieceWorker : public Employee { 189 public: 190 PieceWorker( const char *, const char *, 191 double = 0.0, int = 0); 192 void setWage( double ); 193 void setQuantity( int ); 194 virtual double earnings() const; 195 virtual void print() const; 196 private: 197 double wagePerPiece; // wage for each piece output 198 int quantity; // output for week 199 }; 200 201 #endif 1. PieceWorker Definition (derived class)

  35. 202 // Fig. 10.1: piece1.cpp 203 // Member function definitions for class PieceWorker 204 #include <iostream> 205 206 using std::cout; 207 208 #include "piece1.h" Again, notice the overridden earnings and print functions. They were declared virtual in the base class. 209 210 // Constructor for class PieceWorker 211 PieceWorker::PieceWorker( const char *first, const char *last, 212 double w, int q ) 213 : Employee( first, last ) // call base-class constructor 214 { 215 setWage( w ); 216 setQuantity( q ); 217 } 218 219 // Set the wage 220 void PieceWorker::setWage( double w ) 221 { wagePerPiece = w > 0 ? w : 0; } 222 223 // Set the number of items output 224 void PieceWorker::setQuantity( int q ) 225 { quantity = q > 0 ? q : 0; } 226 227 // Determine the PieceWorker's earnings 228 double PieceWorker::earnings() const 229 { return quantity * wagePerPiece; } 230 231 // Print the PieceWorker's name 232 void PieceWorker::print() const 233 { 234 cout << "\n Piece worker: "; 235 Employee::print(); 236 } 1.1 Function Definitions

  36. 237 // Fig. 10.1: hourly1.h 238 // Definition of class HourlyWorker 239 #ifndef HOURLY1_H 240 #define HOURLY1_H 241 #include "employ2.h" 242 243 class HourlyWorker : public Employee { 244 public: 245 HourlyWorker( const char *, const char *, 246 double = 0.0, double = 0.0); 247 void setWage( double ); 248 void setHours( double ); 249 virtualdouble earnings() const; 250 virtualvoid print() const; 251 private: 252 double wage; // wage per hour 253 double hours; // hours worked for week 254 }; 255 256 #endif 1. HourlyWorker Definition (derived class)

  37. 257 // Fig. 10.1: hourly1.cpp 258 // Member function definitions for class HourlyWorker 259 #include <iostream> 260 261 using std::cout; 262 263 #include "hourly1.h" 264 265 // Constructor for class HourlyWorker 266 HourlyWorker::HourlyWorker( const char *first, 267 const char *last, 268 double w, double h ) 269 : Employee( first, last ) // call base-class constructor 270 { 271 setWage( w ); 272 setHours( h ); 273 } 274 275 // Set the wage 276 void HourlyWorker::setWage( double w ) 277 { wage = w > 0 ? w : 0; } 1.1 Function Definitions

  38. 278 279 // Set the hours worked 280 void HourlyWorker::setHours( double h ) 281 { hours = h >= 0 && h < 168 ? h : 0; } 282 Overridden functions. 283 // Get the HourlyWorker's pay 284 double HourlyWorker::earnings() const 285 { 286 if ( hours <= 40 ) // no overtime 287 return wage * hours; 288 else// overtime is paid at wage * 1.5 289 return 40 * wage + ( hours - 40 ) * wage * 1.5; 290 } 291 292 // Print the HourlyWorker's name 293 void HourlyWorker::print() const 294 { 295 cout << "\n Hourly worker: "; 296 Employee::print(); 297 } 1.1 Function Definitions

  39. 298 // Fig. 10.1: fig10_01.cpp 299 // Driver for Employee hierarchy 300 #include <iostream> 301 302 using std::cout; 303 using std::endl; 304 305 #include <iomanip> 306 307 using std::ios; 308 using std::setiosflags; 309 using std::setprecision; 310 311 #include "employ2.h" 312 #include "boss1.h" 313 #include "commis1.h" 314 #include "piece1.h" 315 #include "hourly1.h" 316 317 void virtualViaPointer( const Employee * ); 318 void virtualViaReference( const Employee & ); 319 320 int main() 321 { 322 // set output formatting 323 cout << setiosflags( ios::fixed | ios::showpoint ) 324 << setprecision( 2 ); 325 1. Load headers

  40. 326 Boss b( "John", "Smith", 800.00 ); 327 b.print(); // static binding Call function print using the object itself. 328 cout << " earned $" << b.earnings(); // static binding Call function print, using a base-class pointer. This uses virtual functions and dynamic binding. 329 virtualViaPointer( &b ); // uses dynamic binding 330 virtualViaReference( b ); // uses dynamic binding 331 Call function print, using a base-class reference. This uses virtual functions and dynamic binding. 332 CommissionWorker c( "Sue", "Jones", 200.0, 3.0, 150 ); 333 c.print(); // static binding 334 cout << " earned $" << c.earnings(); // static binding 335 virtualViaPointer( &c ); // uses dynamic binding 336 virtualViaReference( c ); // uses dynamic binding Take in a baseclass pointer, call the virtual function print. 337 338 PieceWorker p( "Bob", "Lewis", 2.5, 200 ); 339 p.print(); // static binding 340 cout << " earned $" << p.earnings(); // static binding 341 virtualViaPointer( &p ); // uses dynamic binding 342 virtualViaReference( p ); // uses dynamic binding 343 344 HourlyWorker h( "Karen", "Price", 13.75, 40 ); 345 h.print(); // static binding 346 cout << " earned $" << h.earnings(); // static binding 347 virtualViaPointer( &h ); // uses dynamic binding 348 virtualViaReference( h ); // uses dynamic binding 349 cout << endl; 350 return 0; 351 } 352 353 // Make virtual function calls off a base-class pointer 354 // using dynamic binding. 355 void virtualViaPointer( const Employee *baseClassPtr ) 356 { 357 baseClassPtr->print(); 358 cout << " earned $" << baseClassPtr->earnings(); 359 } Boss: John Smith earned $800.00 Boss: John Smith earned $800.00 Boss: John Smith earned $800.00 Commission worker: Sue Jones earned $650.00 Commission worker: Sue Jones earned $650.00 Commission worker: Sue Jones earned $650.00 Piece worker: Bob Lewis earned $500.00 Piece worker: Bob Lewis earned $500.00 Piece worker: Bob Lewis earned $500.00 1.1 Initialize objects 2. Print Hourly worker: Karen Price earned $550.00 Hourly worker: Karen Price earned $550.00 Hourly worker: Karen Price earned $550.00

  41. 360 361 // Make virtual function calls off a base-class reference 362 // using dynamic binding. Take in base class reference, call the virtual function print. 363 void virtualViaReference( const Employee &baseClassRef ) 364 { 365 baseClassRef.print(); 366 cout << " earned $" << baseClassRef.earnings(); 367 } Boss: John Smith earned $800.00 Boss: John Smith earned $800.00 Boss: John Smith earned $800.00 Commission worker: Sue Jones earned $650.00 Commission worker: Sue Jones earned $650.00 Commission worker: Sue Jones earned $650.00 Piece worker: Bob Lewis earned $500.00 Piece worker: Bob Lewis earned $500.00 Piece worker: Bob Lewis earned $500.00 Hourly worker: Karen Price earned $550.00 Hourly worker: Karen Price earned $550.00 Hourly worker: Karen Price earned $550.00 3. Function Definitions Program Output

More Related