Object-Oriented Programming and Inheritance

The specification (employee.h) for the Employee class:
#ifndef EMPLOYEE_H

  #define EMPLOYEE_H
  const int MAX_LENGTH = 50;

  class Employee           
  {
    public:                
      Employee(const char* first, const char* last, 
               float salary, int years);

      void setName(const char* first, const char* last);
      void setSalary(float newSalary);
      void setYears(int numYears);
      void Display(void) const;

    private:               
      char firstName[MAX_LENGTH];  
      char lastName[MAX_LENGTH];   
      float salary;    
      int years;       
  };

#endif

The implementation (employee.cpp) for the Employee class:

#include "employee.h"
#include <string.h>
#include <iostream.h>
#include <iomanip.h>

Employee::Employee(const char* first, const char* last, float sal, int yrs)
{
  strcpy(firstName, first);
  strcpy(lastName, last);
  salary = sal;
  years = yrs;
}

void Employee::setName(const char* first, const char* last)
{
  strcpy(firstName, first);
  strcpy(lastName, last);
}

void Employee::setSalary(float newSalary)
{
  salary = newSalary;
}

void Employee::setYears(int numYears)
{
  years = numYears;
}

void Employee::Display(void) const
{
  cout << "  Name: " << lastName;
  cout << ", " << firstName << endl;
  cout << setprecision(2);
  cout.setf(ios::fixed);
  cout << "Salary: $" << salary << endl;
  cout << " Years: " << years << endl;
}
The specification (manager.h) for the Manager class:
#include "employee.h"

#ifndef MANAGER_H

  #define MANAGER_H

  class Manager : public Employee
  {
    public:
      Manager(const char* first, const char* last, float salary,
              int years, int dept, int emps);

      void setDeptNumber(int dept);
      void setNumEmployees(int emps);
      void Display(void) const;

    private:
      int deptNumber;    // department managed
      int numEmployees;  // employees in department
    };

#endif

The implementation (manager.cpp) for the Manager class:

#include "manager.h"
#include <iostream.h>

Manager::Manager(const char* first, const char* last, float salary, 
                 int years, int dept, int emps) :
         Employee(first, last, salary, years)
{
  deptNumber = dept;
  numEmployees = emps;
}

void Manager::Display(void) const
{
  Employee::Display();
  cout << "  Dept: " << deptNumber << endl;
  cout << "  Emps: " << numEmployees << endl;
}

void Manager::setDeptNumber(int dept)
{
  deptNumber = dept;
}

void Manager::setNumEmployees(int emps)
{
  numEmployees = emps;
}

Trace the execution of the following program through the class hierarchy. What is the output?

#include "employee.h"
#include "manager.h"
#include <iostream.h>
#include <iomanip.h>

void main(void)
{
    // Create an Employee and a Manager
  Employee emp1("John", "Doe", 30000, 2);
  Manager mgr1("Mary", "Smith", 50000, 10, 5, 8); 

    // Display them
  emp1.Display();
  cout << endl;
  mgr1.Display();
  cout << endl;

    // Change the manager's last name
  mgr1.setName("Mary", "Jones");
  mgr1.Display();
  cout << endl;

    // add one employee to this Manager
  mgr1.setNumEmployees(10);
  mgr1.setSalary(80000);
  mgr1.Display();
  cout << endl;
}

  Name: Doe, John
Salary: $30000.00
 Years: 2

  Name: Smith, Mary
Salary: $50000.00
 Years: 10
  Dept: 5
  Emps: 8

  Name: Jones, Mary
Salary: $50000.00
 Years: 10
  Dept: 5
  Emps: 8

  Name: Jones, Mary
Salary: $80000.00
 Years: 10
  Dept: 5
  Emps: 10

Does the following code compile? Trace the execution of the following program. What is the output? Why?
#include "employee.h"
#include "manager.h"
#include <iostream.h>
#include <iomanip.h>

void func1(const Employee& emp)
{
  emp.Display();
  cout << endl;
}

void func2(const Manager& mgr)
{
  mgr.Display();
  cout << endl;
}

void main(void)
{
  Employee emp1("John", "Doe", 30000, 2);
  Manager mgr1("Mary", "Smith", 50000, 10, 5, 8); 

  func1(emp1);  // pass an Employee object
  func2(mgr1);  // pass a Manager object

  func1(mgr1);  // pass a Manager object
}

  Name: Doe, John
Salary: $30000.00
 Years: 2

  Name: Smith, Mary
Salary: $50000.00
 Years: 10
  Dept: 5
  Emps: 8

  Name: Smith, Mary
Salary: $50000.00
 Years: 10

The following code won't compile. Remove the offending line(s) and then trace the execution of the program. What is the output? Why?
#include "employee.h"
#include "manager.h"
#include <iostream.h>
#include <iomanip.h>

void main(void)
{
  Employee emp1("John", "Doe", 30000, 2);
  Manager mgr1("Mary", "Smith", 50000, 10, 5, 8); 

  Employee* empPtr1 = &emp1;
  Manager* mgrPtr1 = &mgr1;

  empPtr1->Display();
  cout << endl;

  mgrPtr1->Display();
  cout << endl;

  empPtr1 = &mgr1;
  empPtr1->setYears(11);
  empPtr1->setNumEmployees(12);
  empPtr1->Display();
  cout << endl;
}
This program creates an array of pointers to Employee objects. It displays each object using a for loop. Make sure you understand what the program is trying to do.
#include "employee.h"
#include "manager.h"
#include <iostream.h>
#include <iomanip.h>

void main(void)
{
    // Create the personnel
  Employee emp1("John", "Doe", 30000, 2);
  Employee emp2("Nigel", "Tufnel", 35000, 4);
  Manager mgr1("Mary", "Smith", 50000, 10, 5, 8); 
  Manager mgr2("Derek", "Smalls", 60000, 13, 6, 5); 

    // Create an array to hold pointers to the 4 objects
  Employee* personnel[4];

    // Assign a pointer for each object
  personnel[0] = &emp1;
  personnel[1] = &emp2;
  personnel[2] = &mgr1;  // a Manager is an Employee
  personnel[3] = &mgr2;  // a Manager is an Employee

    // Loop through and display each object
  for (int i = 0; i < 4; i++)
  {
    personnel[i]->Display();
    cout << endl;
  }
}
This is the output, but it is not quite what we wanted:
 Name: Doe, John
Salary: $30000.00
 Years: 2

  Name: Tufnel, Nigel
Salary: $35000.00
 Years: 4

  Name: Smith, Mary
Salary: $50000.00
 Years: 10

  Name: Smalls, Derek
Salary: $60000.00
 Years: 13

What we really wanted was to have each object display all of its data. The Employee objects displayed all of their data, but the Manager objects only displayed the data that they have in common with an Employee. We really wanted this to display:
  Name: Doe, John
Salary: $30000.00
 Years: 2

  Name: Tufnel, Nigel
Salary: $35000.00
 Years: 4

  Name: Smith, Mary
Salary: $50000.00
 Years: 10
  Dept: 5
  Emps: 8

  Name: Smalls, Derek
Salary: $60000.00
 Years: 13
  Dept: 6
  Emps: 5

Because the personnel[] array is an array of pointers to Employee objects, when the compiler sees the statement:
   personnel[i]->Display();
it generates code to call the Display() method of the Employee class, regardless of what type of object is being pointed at in position i of the personnel[] array. We need a way to tell the compiler not to generate the function call at compile time, but wait until run-time to do so. This is called dynamic binding (or late binding).

C++ has such a mechanism. It's called a virtual function. In order for our example to work, we need to make the Display() method in the Employee class a virtual function. To do so, we merely add the virtual keyword to the function declaration in the specification file:

virtual void Display(void) const;
That's all there is to it! Now, if you run the previous example, you will get the correct output.

Back to Outline