Activity 16-1 - Introduction to Inheritance



Object oriented programming provides for a new dimension of abstraction known as inheritance.  This means that a very general form of a class can be defined and compiled.  Later, more specialized versions of that class may be defined and can inherit all the properties of the previous class.  Inheritance is the process by which a new class - derived class - is created from another class, called the base class.  A derived class automatically has all the member variables and functions that the base class has, and can have additional member functions and/or additional member variables.  Sometimes, a derived class is referred to as the child of a parent class.

A derived class is defined like any other class but has a colon " : ", the reserved word public, and the name of the base class in the first line of the class definition:

class HourlyEmployee : public Employee
{

Now the derived class, HourlyEmployee has all the functions and variables of class Employee and can add additional member variables and member functions.

Here is an example from the text book in which a derived class is being used.

//This is the HEADER FILE hourlyemployee.h.
//This is the INTERFACE for the class HourlyEmployee.
#ifndef HOURLYEMPLOYEE_H
#define HOURLYEMPLOYEE_H

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

using namespace std;

namespace savitchemployees
{

    class HourlyEmployee : public Employee
    {
    public:
        HourlyEmployee();
        HourlyEmployee(string new_name, string new_ssn, double new_wage_rate, double new_hours);
        void set_rate(double new_wage_rate);
        double get_rate();
        void set_hours(double hours_worked);
        double get_hours();
        void give_raise(double amount);
        void print_check();
    private:
        double wage_rate;
        double hours;
    };

}//savitchemployees

#endif //HOURLYMPLOYEE_H

As you can see the derived HourlyEmployee class, in addition to all member functions and variable members that it inherits from the Employee class, it has several additional member functions and variable members defined in its body.

Here is another derived class:

//This is the HEADER FILE salariedemployee.h.
//This is the INTERFACE for the class SalariedEmployee.
#ifndef SALARIEDEMPLOYEE_H
#define SALARIEDMPLOYEE_H

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

using namespace std;

namespace savitchemployees
{

    class SalariedEmployee : public Employee
    {
    public:
        SalariedEmployee();
        SalariedEmployee (string new_name, string new_ssn, double new_weekly_salary);
        double get_salary();
        void change_salary(double new_salary);
        void print_check();
        void give_raise(double amount);
    private:
        double salary;   //weekly
    };

}//savitchemployees

#endif //SALARIEDEMPLOYEE_H

In this example, the derived class is SalariedEmployee and again has additional member functions and variable members to the ones that are already inherited from  the Employee class.

It is possible to take a member function from the parent's class and redefine it in the body of the child class.  This is called redefining the inherited member function.  For example, the print_check function is redefined in the HourlyEmployee class.   To redefine a function, simply list it in the class definition and give it a new definition, just as you do with any other function.

Here is the class Employee that is considered as the parent for the above two classes.

//This is the HEADER FILE employee.h.
//This is the INTERFACE for the class Employee.
//This is primarily intended to be used as a base class to derive
//classes for different kinds of employees.
#ifndef EMPLOYEE_H
#define EMPLOYEE_H

#include <string>
using namespace std;

namespace savitchemployees
{

    class Employee
    {
    public:
        Employee();
        Employee(string new_name, string new_ssn);
        string get_name();
        string get_ssn();
        void change_name(string new_name);
        void change_ssn(string new_ssn);
        void print_check();
        void give_raise(double amount);
    protected:
        string name;
        string ssn;
        double net_pay;
    };

}//savitchemployees

#endif //EMPLOYEE_H

The definition for Employee class is:

//******************************************************
//This is the IMPLEMENTATION FILE: employee.cpp
//This is the IMPLEMENTATION for the class Employee.
//The interface for the class Employee is in the header file employee.h.
#include <iostream>
#include <string>
#include <cstdlib>
#include "employee.h"
using namespace std;

namespace savitchemployees
{

    Employee::Employee() // default is to fetch data from keyboard
    {
        cout << "Enter employee name, followed by return.:\n";
        getline(cin, name);
        cout  << endl << "Enter employee social security number,"
              << " followed by return.:\n";
        getline(cin, ssn);
        cin.ignore(10000, '\n');
        cout << endl;
    }

    Employee::Employee(string new_name, string new_number) :
        name(new_name), ssn(new_number) //initializer list
    {
        //deliberately empty
    }

    string Employee::get_name()
    {
        return name;
    }

    string Employee::get_ssn()
    {
        return ssn;
    }

    void Employee::change_name(string new_name)
    {
        name = new_name;
    }

    void Employee::change_ssn (string new_ssn)
    {
        ssn = new_ssn;
    }

    void Employee::print_check()
    {
        cout  << "\nERROR: print_check FUNCTION CALLED FOR AN \n"
              << "UNDIFFERENTIATED EMPLOYEE. Aborting the program.\n"
              << "Check with the author of the program about this bug.\n";
        exit(1);
    }

    void Employee::give_raise(double amount)
    {
        cout << "\nERROR: give_raise FUNCTION CALLED FOR AN \n"
               << "UNDIFFERENTIATED EMPLOYEE. Aborting the program.\n"
               << "Check with the author of the program about this bug.\n";
        exit(1);
    }

}//savitchemployees
// ********************************************************

Constructors in Derived Classes
A constructor in a base class is NOT inherited in the derived class, but you can invoke a constructor of the base class within the definition of a derived class constructor, and that is all you need or normally want.    A constructor for a derived class uses a constructor from the base class in a special way.  A constructor for the base class initializes all the data inherited from the base class.  There is a special syntax for defining base class constructors.

HourlyEmployee::HourlyEmployee(string new_name,   string new_number, double new_wage_rate, double new_hours):Employee(new_name, new_number), wage_rate(new_wage_rate), hours(new_hours)

The part:
HourlyEmployee(string new_name,   string new_number, double new_wage_rate, double new_hours)

is an invocation of the two argument constructor for the base class Employee.  We have used :: before it as we did when we defined all member functions.  Everything   after : , i.e.;

Employee(new_name, new_number), wage_rate(new_wage_rate), hours(new_hours)

is the initialization section of the constructor definition for the constructor HourlyEmployee::HourlyEmployee.

Here is another example:
HourlyEmployee::HourlyEmployee( ) : Employee( ), wage_rate(0), hours(0)
{
        // deliberately left empty
}

In this constructor definition the default (zero argument) version of the base class constructor is called to initialize the inherited member variables.

Exercise 16.1
Use the above three header files and the following two implementation programs, hourlyemployee.cpp, and salariedemployee.cpp.  Redefine the function give_raise in both HourlyEmployee and SalariedEmployee such that:
    1) Hourly_bases employees receive 10% raise on their hourly rate (wage_rate)
    2) Salaried employees receive 6% raise of their salary