Class SalariedEmployee
(Figs. 12.11–12.12) derives from class Employee
(line 9 of Fig. 12.11). The public
member functions include a constructor that takes a first name, a last name, a social security number and a weekly salary as arguments (lines 12–13); a virtual
destructor (line 14); a set function to assign a new nonnegative value to data member weeklySalary
(line 16); a get function to return weeklySalary
’s value (line 17); a virtual
function earnings
that calculates a SalariedEmployee
’s earnings (line 20) and a virtual
function print
(line 21) that outputs the employee’s type, namely, "salaried employee: "
followed by employee-specific information produced by base class Employee
’s print
function and SalariedEmployee
’s getWeeklySalary
function.
1 // Fig. 12.11: SalariedEmployee.h
2 // SalariedEmployee class derived from Employee.
3 #ifndef SALARIED_H
4 #define SALARIED_H
5
6 #include <string> // C++ standard string class
7 #include "Employee.h" // Employee class definition
8
9 class SalariedEmployee : public Employee
10 {
11 public:
12 SalariedEmployee( const std::string &, const std::string &,
13 const std::string &, double = 0.0 );
14 virtual ~SalariedEmployee() { } // virtual destructor
15
16 void setWeeklySalary( double ); // set weekly salary
17 double getWeeklySalary() const; // return weekly salary
18
19 // keyword virtual signals intent to override
20 virtual double earnings() const override; // calculate earnings
21 virtual void print() const override; // print object
22 private:
23 double weeklySalary; // salary per week
24 }; // end class SalariedEmployee
25
26 #endif // SALARIED_H
1 // Fig. 12.12: SalariedEmployee.cpp
2 // SalariedEmployee class member-function definitions.
3 #include <iostream>
4 #include <stdexcept>
5 #include "SalariedEmployee.h" // SalariedEmployee class definition
6 using namespace std;
7
8 // constructor
9 SalariedEmployee::SalariedEmployee( const string &first,
10 const string &last, const string &ssn, double salary )
11 : Employee( first, last, ssn )
12 {
13 setWeeklySalary( salary );
14 } // end SalariedEmployee constructor
15
16 // set salary
17 void SalariedEmployee::setWeeklySalary( double salary )
18 {
19 if ( salary >= 0.0 )
20 weeklySalary = salary;
21 else
22 throw invalid_argument( "Weekly salary must be >= 0.0" );
23 } // end function setWeeklySalary
24
25 // return salary
26 double SalariedEmployee::getWeeklySalary() const
27 {
28 return weeklySalary;
29 } // end function getWeeklySalary
30
31 // calculate earnings;
32 // override pure virtual function earnings in Employee
33 double SalariedEmployee::earnings() const
34 {
35 return getWeeklySalary();
36 } // end function earnings
37
38 // print SalariedEmployee's information
39 void SalariedEmployee::print() const
40 {
41 cout << "salaried employee: ";
42 Employee::print(); // reuse abstract base-class print function
43 cout << "
weekly salary: " << getWeeklySalary();
44 } // end function print
Figure 12.12 contains the member-function definitions for SalariedEmployee
. The class’s constructor passes the first name, last name and social security number to the Employee
constructor (line 11) to initialize the private
data members that are inherited from the base class, but not directly accessible in the derived class. Function earnings
(lines 33–36) overrides pure virtual
function earnings
in Employee
to provide a concrete implementation that returns the SalariedEmployee
’s weekly salary. If we did not define earnings
, class SalariedEmployee
would be an abstract class, and any attempt to instantiate a SalariedEmployee
object would cause a compilation error. In class SalariedEmployee
’s header, we declared member functions earnings
and print
as virtual
(lines 20–21 of Fig. 12.11)—actually, placing the virtual
keyword before these member functions is redundant. We defined them as virtual
in base class Employee
, so they remain virtual
functions throughout the class hierarchy. Explicitly declaring such functions virtual
at every level of the hierarchy promotes program clarity. Not declaring earnings
as pure virtual
signals our intent to provide an implementation in this concrete class.
Function print
of class SalariedEmployee
(lines 39–44 of Fig. 12.12) overrides Employee
function print
. If class SalariedEmployee
did not override print
, SalariedEmployee
would inherit the Employee
version of print
. In that case, SalariedEmployee
’s print
function would simply return the employee’s full name and social security number, which does not adequately represent a SalariedEmployee
. To print a SalariedEmployee
’s complete information, the derived class’s print
function outputs "salaried employee: "
followed by the base-class Employee
-specific information (i.e., first name, last name and social security number) printed by invoking the base class’s print
function using the scope resolution operator (line 42)—this is a nice example of code reuse. Without the scope resolution operator, the print
call would cause infinite recursion. The output produced by SalariedEmployee
’s print
function also contains the employee’s weekly salary obtained by invoking the class’s getWeeklySalary
function.