#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:
The specification (manager.h) for the Manager 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; }
#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?
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 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
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 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
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) { 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 is the output, but it is not quite what we wanted:#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; } }
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 Name: Smalls, Derek Salary: $60000.00 Years: 13
Because the personnel[] array is an array of pointers to Employee objects, when the compiler sees the statement: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
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:
That's all there is to it! Now, if you run the previous example, you will get the correct output.virtual void Display(void) const;