// Виртуални функции и полиморфизъм I // -- Клас Employee и производни класове. // // employ2.h // Abstract base class Employee #ifndef EMPLOY2_H #define EMPLOY2_H #include class Employee { public: Employee( const char *, const char * ); ~Employee(); // destructor reclaims memory const char *getFirstName() const; const char *getLastName() const; // Pure virtual function makes Employee abstract base class virtual double earnings() const = 0; // pure virtual virtual void print() const; // virtual private: char *firstName; char *lastName; }; #endif ------ //employ2.cpp // Member function definitions for // abstract base class Employee. // Note: No definitions given for pure virtual functions. #include #include #include "employ2.h" // Constructor dynamically allocates space for the // first and last name and uses strcpy to copy // the first and last names into the object. Employee::Employee( const char *first, const char *last ) { firstName = new char[ strlen( first ) + 1 ]; assert( firstName != 0 ); // test that new worked strcpy( firstName, first ); lastName = new char[ strlen( last ) + 1 ]; assert( lastName != 0 ); // test that new worked strcpy( lastName, last ); } // Destructor deallocates dynamically allocated memory Employee::~Employee() { delete [] firstName; delete [] lastName; } // Return a pointer to the first name // Const return type prevents caller from modifying private // data. Caller should copy returned string before destructor // deletes dynamic storage to prevent undefined pointer. const char *Employee::getFirstName() const { return firstName; // caller must delete memory } // Return a pointer to the last name // Const return type prevents caller from modifying private // data. Caller should copy returned string before destructor // deletes dynamic storage to prevent undefined pointer. const char *Employee::getLastName() const { return lastName; // caller must delete memory } // Print the name of the Employee void Employee::print() const { cout << firstName << ' ' << lastName; } --------------------------------- // boss1.h // Boss class derived from Employee #ifndef BOSS1_H #define BOSS1_H #include "employ2.h" class Boss : public Employee { public: Boss( const char *, const char *, double = 0.0 ); void setWeeklySalary( double ); virtual double earnings() const; virtual void print() const; private: double weeklySalary; }; #endif ------ // Fig. 10.1: boss1.cpp // Member function definitions for class Boss #include "boss1.h" // Constructor function for class Boss Boss::Boss( const char *first, const char *last, double s ) : Employee( first, last ) // call base-class constructor { setWeeklySalary( s ); } // Set the Boss's salary void Boss::setWeeklySalary( double s ) { weeklySalary = s > 0 ? s : 0; } // Get the Boss's pay double Boss::earnings() const { return weeklySalary; } // Print the Boss's name void Boss::print() const { cout << "\n Boss: "; Employee::print(); } ----------------------------------- // Fig. 10.1: commis1.h // CommissionWorker class derived from Employee #ifndef COMMIS1_H #define COMMIS1_H #include "employ2.h" class CommissionWorker : public Employee { public: CommissionWorker( const char *, const char *, double = 0.0, double = 0.0, int = 0 ); void setSalary( double ); void setCommission( double ); void setQuantity( int ); virtual double earnings() const; virtual void print() const; private: double salary; // base salary per week double commission; // amount per item sold int quantity; // total items sold for week }; #endif ------ // Fig. 10.1: commis1.cpp // Member function definitions for class CommissionWorker #include #include "commis1.h" // Constructor for class CommissionWorker CommissionWorker::CommissionWorker( const char *first, const char *last, double s, double c, int q ) : Employee( first, last ) // call base-class constructor { setSalary( s ); setCommission( c ); setQuantity( q ); } // Set CommissionWorker's weekly base salary void CommissionWorker::setSalary( double s ) { salary = s > 0 ? s : 0; } // Set CommissionWorker's commission void CommissionWorker::setCommission( double c ) { commission = c > 0 ? c : 0; } // Set CommissionWorker's quantity sold void CommissionWorker::setQuantity( int q ) { quantity = q > 0 ? q : 0; } // Determine CommissionWorker's earnings double CommissionWorker::earnings() const { return salary + commission * quantity; } // Print the CommissionWorker's name void CommissionWorker::print() const { cout << "\nCommission worker: "; Employee::print(); } ---------------------------------- // Fig. 10.1: hourly1.h // Definition of class HourlyWorker #ifndef HOURLY1_H #define HOURLY1_H #include "employ2.h" class HourlyWorker : public Employee { public: HourlyWorker( const char *, const char *, double = 0.0, double = 0.0); void setWage( double ); void setHours( double ); virtual double earnings() const; virtual void print() const; private: double wage; // wage per hour double hours; // hours worked for week }; #endif ------ // Fig. 10.1: hourly1.cpp // Member function definitions for class HourlyWorker #include #include "hourly1.h" // Constructor for class HourlyWorker HourlyWorker::HourlyWorker( const char *first, const char *last, double w, double h ) : Employee( first, last ) // call base-class constructor { setWage( w ); setHours( h ); } // Set the wage void HourlyWorker::setWage( double w ) { wage = w > 0 ? w : 0; } // Set the hours worked void HourlyWorker::setHours( double h ) { hours = h >= 0 && h < 168 ? h : 0; } // Get the HourlyWorker's pay double HourlyWorker::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; } // Print the HourlyWorker's name void HourlyWorker::print() const { cout << "\n Hourly worker: "; Employee::print(); } ----------------------------------- // Fig. 10.1: piece1.h // PieceWorker class derived from Employee #ifndef PIECE1_H #define PIECE1_H #include "employ2.h" class PieceWorker : public Employee { public: PieceWorker( const char *, const char *, double = 0.0, int = 0); void setWage( double ); void setQuantity( int ); virtual double earnings() const; virtual void print() const; private: double wagePerPiece; // wage for each piece output int quantity; // output for week }; #endif ------ // Fig. 10.1: piece1.cpp // Member function definitions for class PieceWorker #include #include "piece1.h" // Constructor for class PieceWorker PieceWorker::PieceWorker( const char *first, const char *last, double w, int q ) : Employee( first, last ) // call base-class constructor { setWage( w ); setQuantity( q ); } // Set the wage void PieceWorker::setWage( double w ) { wagePerPiece = w > 0 ? w : 0; } // Set the number of items output void PieceWorker::setQuantity( int q ) { quantity = q > 0 ? q : 0; } // Determine the PieceWorker's earnings double PieceWorker::earnings() const { return quantity * wagePerPiece; } // Print the PieceWorker's name void PieceWorker::print() const { cout << "\n Piece worker: "; Employee::print(); } -------------------------------- // Fig. 10.1: fig10_01.cpp // Driver for Employee hierarchy #include #include #include "employ2.h" #include "boss1.h" #include "commis1.h" #include "piece1.h" #include "hourly1.h" void virtualViaPointer( const Employee * ); void virtualViaReference( const Employee & ); int main() { // set output formatting cout << setiosflags( ios::fixed | ios::showpoint ) << setprecision( 2 ); Boss b( "John", "Smith", 800.00 ); b.print(); // static binding cout << " earned $" << b.earnings(); // static binding virtualViaPointer( &b ); // uses dynamic binding virtualViaReference( b ); // uses dynamic binding CommissionWorker c( "Sue", "Jones", 200.0, 3.0, 150 ); c.print(); // static binding cout << " earned $" << c.earnings(); // static binding virtualViaPointer( &c ); // uses dynamic binding virtualViaReference( c ); // uses dynamic binding PieceWorker p( "Bob", "Lewis", 2.5, 200 ); p.print(); // static binding cout << " earned $" << p.earnings(); // static binding virtualViaPointer( &p ); // uses dynamic binding virtualViaReference( p ); // uses dynamic binding HourlyWorker h( "Karen", "Price", 13.75, 40 ); h.print(); // static binding cout << " earned $" << h.earnings(); // static binding virtualViaPointer( &h ); // uses dynamic binding virtualViaReference( h ); // uses dynamic binding cout << endl; return 0; } // Make virtual function calls off a base-class pointer // using dynamic binding. void virtualViaPointer( const Employee *baseClassPtr ) { baseClassPtr->print(); cout << " earned $" << baseClassPtr->earnings(); } // Make virtual function calls off a base-class reference // using dynamic binding. void virtualViaReference( const Employee &baseClassRef ) { baseClassRef.print(); cout << " earned $" << baseClassRef.earnings(); } -----------------------------------------------------------