12.6.1. Creating Abstract Base Class Employee

Class Employee (Figs. 12.912.10, discussed in further detail shortly) provides functions earnings and print, in addition to various get and set functions that manipulate Employee’s data members. An earnings function certainly applies generally to all employees, but each earnings calculation depends on the employee’s class. So we declare earnings as pure virtual in base class Employee because a default implementation does not make sense for that function—there is not enough information to determine what amount earnings should return. Each derived class overrides earnings with an appropriate implementation. To calculate an employee’s earnings, the program assigns the address of an employee’s object to a base class Employee pointer, then invokes the earnings function on that object. We maintain a vector of Employee pointers, each of which points to an Employee object. Of course, there cannot be Employee objects, because Employee is an abstract class—because of inheritance, however, all objects of all concrete derived classes of Employee may nevertheless be thought of as Employee objects. The program iterates through the vector and calls function earnings for each Employee object. C++ processes these function calls polymorphically. Including earnings as a pure virtual function in Employee forces every direct derived class of Employee that wishes to be a concrete class to override earnings.

Function print in class Employee displays the first name, last name and social security number of the employee. As we’ll see, each derived class of Employee overrides function print to output the employee’s type (e.g., "salaried employee:") followed by the rest of the employee’s information. Function print in the derived classes could also call earnings, even though earnings is a pure-virtual function in base class Employee.

The diagram in Fig. 12.8 shows each of the four classes in the hierarchy down the left side and functions earnings and print across the top. For each class, the diagram shows the desired results of each function. Italic text represents where the values from a particular object are used in the earnings and print functions. Class Employee specifies “= 0” for function earnings to indicate that this is a pure virtual function and hence has no implementation. Each derived class overrides this function to provide an appropriate implementation. We do not list base class Employee’s get and set functions because they’re not overridden in any of the derived classes—each of these functions is inherited and used “as is” by each of the derived classes.

Image

Fig. 12.8. Polymorphic interface for the Employee hierarchy classes.

Employee Class Header

Let’s consider class Employee’s header (Fig. 12.9). The public member functions include a constructor that takes the first name, last name and social security number as arguments (lines 11–12); a virtual destructor (line 13); set functions that set the first name, last name and social security number (lines 15, 18 and 21, respectively); get functions that return the first name, last name and social security number (lines 16, 19 and 22, respectively); pure virtual function earnings (line 25) and virtual function print (line 26).


 1   // Fig. 12.9: Employee.h
 2   // Employee abstract base class.
 3   #ifndef EMPLOYEE_H
 4   #define EMPLOYEE_H
 5
 6   #include <string> // C++ standard string class
 7
 8   class Employee
 9   {
10   public:
11      Employee( const std::string &, const std::string &,
12         const std::string & );
13      virtual ~Employee() { } // virtual destructor
14
15      void setFirstName( const std::string & ); // set first name
16      std::string getFirstName() const; // return first name
17
18      void setLastName( const std::string & ); // set last name
19      std::string getLastName() const; // return last name
20
21      void setSocialSecurityNumber( const std::string & ); // set SSN
22      std::string getSocialSecurityNumber() const; // return SSN
23
24      // pure virtual function makes Employee an abstract base class
25      virtual double earnings() const = 0; // pure virtual          
26      virtual void print() const; // virtual                        
27   private:
28      std::string firstName;
29      std::string lastName;
30      std::string socialSecurityNumber;
31   }; // end class Employee
32
33   #endif // EMPLOYEE_H


Fig. 12.9. Employee abstract base class.

Recall that we declared earnings as a pure virtual function because first we must know the specific Employee type to determine the appropriate earnings calculations. Declaring this function as pure virtual indicates that each concrete derived class must provide an earnings implementation and that a program can use base-class Employee pointers to invoke function earnings polymorphically for any type of Employee.

Employee Class Member-Function Definitions

Figure 12.10 contains the member-function definitions for class Employee. No implementation is provided for virtual function earnings. The Employee constructor (lines 9–14) does not validate the social security number. Normally, such validation should be provided.


 1   // Fig. 12.10: Employee.cpp
 2   // Abstract-base-class Employee member-function definitions.
 3   // Note: No definitions are given for pure virtual functions.
 4   #include <iostream>
 5   #include "Employee.h" // Employee class definition
 6   using namespace std;
 7
 8   // constructor
 9   Employee::Employee( const string &first, const string &last,
10      const string &ssn )
11      : firstName( first ), lastName( last ), socialSecurityNumber( ssn )
12   {
13      // empty body
14   } // end Employee constructor
15
16   // set first name
17   void Employee::setFirstName( const string &first )
18   {
19      firstName = first;
20   } // end function setFirstName
21
22   // return first name
23   string Employee::getFirstName() const
24   {
25      return firstName;
26   } // end function getFirstName
27
28   // set last name
29   void Employee::setLastName( const string &last )
30   {
31      lastName = last;
32   } // end function setLastName
33
34   // return last name
35   string Employee::getLastName() const
36   {
37      return lastName;
38   } // end function getLastName
39
40   // set social security number
41   void Employee::setSocialSecurityNumber( const string &ssn )
42   {
43      socialSecurityNumber = ssn; // should validate
44   } // end function setSocialSecurityNumber
45
46   // return social security number
47   string Employee::getSocialSecurityNumber() const
48   {
49      return socialSecurityNumber;
50   } // end function getSocialSecurityNumber
51
52   // print Employee's information (virtual, but not pure virtual)
53   void Employee::print() const
54   {
55      cout << getFirstName() << ' ' << getLastName()
56         << " social security number: " << getSocialSecurityNumber();
57   } // end function print


Fig. 12.10. Employee class implementation file.

The virtual function print (lines 53–57) provides an implementation that will be overridden in each of the derived classes. Each of these functions will, however, use the abstract class’s version of print to print information common to all classes in the Employee hierarchy.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.118.253.33