Lec10. Inheritance

Download as pptx, pdf, or txt
Download as pptx, pdf, or txt
You are on page 1of 20

Chapter 14

Inheritance

Copyright © 2017 Pearson Education, Ltd.


All rights reserved.
Introduction to Inheritance
• Object-oriented programming
– Powerful programming technique
– Provides abstraction dimension called inheritance
• General form of class is defined
– Specialized versions then inherit properties of general class
– And add to it/modify it’s functionality for it’s appropriate use
• Inheritance basics: new class inherited from another class
– Base class: "General" class from which others derive. Also called parent class
– Derived class: New class that is a child of parent or base class
• Automatically has base class’s:
– Member variables
– Member functions
• Can then add additional or redefine existing member functions and variables

14-2
Derived Classes Through Example
• Class of "Employees" Employees
is a
– Composed of:
Salaried Hourly
• Salaried employees
Employees Employees
• Hourly employees
– No one is just an "employee“. Each is "subset" of employees
• Another might be those paid fixed wage each month or week
• General concept of employee is helpful!
– All have names
– All have social security numbers
– Associated functions for these "basics" are same among all employees
• So "general" class can contain all these "things" about employees

14-3
//This is the interface for class Employee intended to be used as base class to derive classes for different kinds of
// employees. Many members of "employee" class apply to all types of employees. We won’t have "objects" of this
// class
#ifndef EMPLOYEE_H
#define EMPLOYEE_H Employee Class
#include <string>
using std::string; employee.h
class Employee {
public:
Employee( );
Employee( const string& theName, const string& theSsn);
//Accessor functions
string getName( ) const;
string getSsn( ) const;
double getNetPay( ) const;
void printCheck( ) const;
//Mutator functions
void setName( const string& newName);
void setSsn( const string& newSsn);
void setNetPay( double newNetPay);
private:
string name;
string ssn;
double netPay;
};
#endif //EMPLOYEE_H
14-4
//Implementation for the Base Class Employee.
#include <string> Employee Class
#include <cstdlib>
#include <iostream>
employee.cpp
#include "employee.h"
using namespace std;
Employee::Employee( ) : name("No name yet"), ssn("No number yet"), netPay(0){}
Employee::Employee( const string& theName, const string& theNumber)
: name(theName), ssn(theNumber), netPay(0){}
string Employee::getName( ) const {
return name;
}
string Employee::getSsn( ) const{
return ssn;
}
double Employee::getNetPay( ) const {
return netPay;
}
void Employee::setName( const string& newName){
name = newName;
}
void Employee::setSsn( const string& newSsn) {
ssn = newSsn;
}
void Employee::setNetPay ( double newNetPay){
netPay = newNetPay;
}
void Employee::printCheck( ) const {
cout << "\nERROR: printCheck FUNCTION CALLED FOR AN \n"
<< "UNDIFFERENTIATED EMPLOYEE. Aborting the program.\n"
exit(1); 14-5
}
Employee Class
• Many members of "employee" class apply to all types of employees
– Accessor functions
– Mutator functions
– Most data items: SSN, Name, Pay
• Derived classes from base class Employee :
– Automatically have "inherit" member variables and member functions
– Can then redefine existing members and/or add new members
• Consider printCheck() function:
– Will always be "redefined" in derived classes, so different employee types can
have different checks
– Makes no sense really for "undifferentiated“ employee
– So function printCheck()in Employee class says just that
• Error message stating "printCheck called for undifferentiated employee!!
Aborting…" 14-6
// Interface for the Derived Class HourlyEmployee
#ifndef HOURLYEMPLOYEE_H
#define HOURLYEMPLOYEE_H
#include <string> HourlyEmployee Class
#include "employee.h " HourlyEmployee.h
using namespace std;
class HourlyEmployee : public Employee {
public:
HourlyEmployee( );
HourlyEmployee( const string& theName, const string& theSsn,
double theWageRate, double theHours);
void setRate( double newWageRate);
double getRate( ) const;
void setHours( double hoursWorked);
double getHours( ) const;
void printCheck( );
List only the declaration of an
private
inherited member function if you
double wageRate;
want to change the definition of
double hours;
the function.
};
#endif //HOURLYEMPLOYEE_H

14-7 14-7
// Interface for the Derived Class SalariedEmployee
#ifndef SALARIEDEMPLOYEE_H
#define SALARIEDMPLOYEE_H
#include <string> SalariedEmployee Class
#include "employee.h" SalariedEmployee.h
using namespace std;

class SalariedEmployee : public Employee {


public:
SalariedEmployee( );
SalariedEmployee( const string& theName, const string& theSsn,
double salary);
double getSalary( ) const;
void setSalary( double newSalary);
void printCheck( );
private
double salary; //weekly
};
#endif //SALARIEDEMPLOYEE_H

14-8 14-8
//This is the implementation for the class HourlyEmployee
#include <string>
#include <iostream> HourlyEmployee Class
#include "hourlyemployee.h"
HourlyEmployee.cpp
using namespace std;

HourlyEmployee::HourlyEmployee( ) :Employee(),wageRate(0), hours(0) {}

HourlyEmployee::HourlyEmployee( const string& theName, const string& theNumber,


double theWageRate, double theHours)
:Employee(theName, theNumber), wageRate(theWageRate), hours(theHours) {}

void HourlyEmployee::setRate( double newWageRate) {wageRate = newWageRate;}

double HourlyEmployee::getRate( ) const { return wageRate;}

void HourlyEmployee::setHours( double hoursWorked) {hours = hoursWorked;}

double HourlyEmployee::getHours( ) const { return hours;} We have chosen to set netPay


as part of the printCheck
void HourlyEmployee::printCheck( ) { function because that is
setNetPay(hours * wageRate); when it is used. In any event,
cout << "\n__________________________________________\n"; this is an accounting question,
cout << "Pay to the order of " << getName( ) << endl; not a programming question.
cout << "The sum of " << getNetPay( ) << " Dollars\n"; But, note that C++ allows us
cout << "__________________________________________\n";
to drop the const on the
cout << "Check Stub: NOT NEGOTIABLE\n";
function printCheck when
cout << "Employee Number: " << getSsn( ) << endl;
cout << "Hourly Employee. \nHours worked: " << hours
we redefine it in a derived
<< " Rate: " << wageRate << " Pay: " class.
<< getNetPay( ) << endl;
cout << "__________________________________________\n"; 14-9 14-9
}
//This is the implementation for the class salariedEmployee
#include <string>
#include <iostream>
#include "salariedemployee.h"
salariedEmployeeClass
salariedEmployee.cpp
using namespace std;

SalariedEmployee::SalariedEmployee( ) :Employee(), salary(0){}

SalariedEmployee::SalariedEmployee( const string& theName,


const string& theNumber, double salary)
:Employee(theName, theNumber), salary(salary){}

double SalariedEmployee::getSalary( ) const {return salary;}

void SalariedEmployee::setSalary( double newSalary) { salary = newSalary;}

void SalariedEmployee::printCheck( ){
setNetPay(salary);
cout << "\n__________________________________________\n";
cout << "Pay to the order of " << getName( ) << endl;
cout << "The sum of " << getNetPay( ) << " Dollars\n";
cout << "__________________________________________\n";
cout << "Check Stub: NOT NEGOTIABLE\n";
cout << "Employee Number: " << getSsn( ) << endl;
cout << "Salaried Employee. Regular Pay:"
<< getNetPay( ) << endl;
cout << "__________________________________________\n";
}
14-10 14-10
#include <iostream>
#include "hourlyemployee.h"
#include "salariedemployee.h" tester.cpp
using std::cout;
using std::endl;

int main( ){
HourlyEmployee joe;
joe.setName("Mighty Joe");
joe.setSsn("123-45-6789");
joe.setRate(20.50);
joe.setHours(40);
cout << "Check for " << joe.getName( )
<< " for " << joe.getHours( ) << " hours.\n";
joe.printCheck( );
cout << endl;
SalariedEmployee boss("Mr. Big Shot", "987-65-4321", 10500.50);
cout << "Check for " << boss.getName( ) << endl;
boss.printCheck( );
return 0;
}

14-11 14-11
HourlyEmployee Class Interface
• Note definition begins same as any other
– #ifndef structure, then includes required libraries and employee.h!
– And, the heading: class HourlyEmployee : public Employee{
• Specifies "publicly inherited" from Employee class

• Derived class interface only lists new or "to be redefined" members


– Since all others inherited are already defined i.e.: ssn, name, etc.
– HourlyEmployee adds:
• Constructors
• wageRate, hours member variables
• setRate(), getRate(), setHours(), getHours() member functions
– HourlyEmployee redefines:
• printCheck() member function
• This "overrides" the printCheck() function implementation from Employee
class 14-12
Constructors in Derived Classes
• Base class constructors are NOT inherited in derived classes!
– But they can be invoked within derived class constructor
• Base class constructor must initialize all base class member
variables
– Those inherited by derived class
– So derived class constructor simply calls it
• "First" thing derived class constructor does
• Consider syntax for HourlyEmployee constructor:

HourlyEmployee::HourlyEmployee(string theName, string theNumber,


double theWageRate, double theHours)
: Employee(theName, theNumber),
wageRate(theWageRate), hours(theHours)
{
//Deliberately empty
}

• Portion after is "initialization section“ includes invocation of Employee


constructor
14-13
Another HourlyEmployee Constructor
• A second constructor:
HourlyEmployee::HourlyEmployee(): Employee(), wageRate(0), hours(0)
{
//Deliberately empty
}

• Default version of base class constructor is called (no arguments)


• Derived class constructor should always invoke one of the base
class’s constructors
– If you do not: Default base class constructor automatically called
• Equivalent constructor definition:

HourlyEmployee::HourlyEmployee(): wageRate(0), hours(0)


{ }

14-14
Pitfall: Base Class Private Member Data and Functions
• Derived class "inherits" private member variables
– But still cannot directly access them
– Not even through derived class member functions!
– Private member variables can ONLY be accessed "by name" in member
functions of the class they’re defined in
• Same holds for base class private member functions
– Cannot be accessed outside interface and implementation of base class
– Not even in derived class member function definitions

14-15
The protected: Qualifier
• you cannot access a base class private member variable or private
member from a derived class
• Qualifier protected
– Allows access "by name" base class member variables and functions in
derived class
• But nowhere else
• Still no access "by name" in other classes

– In class where it’s defined  acts like private


– Considered "protected" in derived class
• To allow future derivations

– Many feel this "violates" information hiding

14-16
Redefinition of Member Functions
• Implementation of derived class will:
– Define new member functions
– Redefine inherited functions as declared
• Redefining vs. Overloading
– Very different!
– Redefining in derived class: SAME parameter list
• Essentially "re-writes" same function
– Overloading: Different parameter list
• Defined "new" function that takes different parameters
• Overloaded functions must have different signatures
• Function’s Signature is:
– Function’s name
– Sequence of types in parameter list: order, number, types
• Signature does NOT include: Return type, const keyword, &
14-17
Accessing Redefined Base Function
• When redefined in derived class, base class’s definition not "lost"
• We can specify it is used:
Employee JaneE;
HourlyEmployee SallyH;
JaneE.printCheck(); // calls Employee’s printCheck function
SallyH.printCheck(); // calls HourlyEmployee printCheck function
SallyH.Employee::printCheck(); // Calls Employee’s printCheck function!

• Not typical, but useful sometimes


• All "normal" functions in base class are inherited in derived class
– Exceptions:
• Constructors (we’ve seen)
• Destructors
• Copy constructor: But if not defined in derived class, C++ generates "default" one
– default copy constructor copies contents and does not work correctly with pointers or
dynamic allocation
» Recall need to define one for pointers!
• Assignment operator: If not defined  default
14-18
Assignment Operators and Copy Constructors
• Overloaded = operators and copy constructors are NOT inherited
– But can be used in derived class definitions (Typically MUST be used!)
• Similar to how derived class constructor invokes base class constructor

• Examples: given "Derived" is derived from "Base":


– Calling = operator from base class takes care of all inherited member variables
– Would then set new variables from derived class…

Derived& Derived::operator =(const Derived & rightSide){


Base::operator =(rightSide); //This takes care of the inherited member variables and their data

}
Derived::Derived(const Derived& Object): Base(Object), …
{…}

– Similarly, invocation of base copy constructor sets inherited member variables


of derived class object being created
– Note Object is of type Derived; but it’s also of type Base, so argument is valid
14-19
Destructors in Derived Classes
• If base class destructor functions correctly
– Easy to write derived class destructor
• When derived class destructor is invoked:
– Automatically calls base class destructor!
• So derived class destructors need only be concerned with derived
class variables
– And any data they "point" to
– Base class destructor handles inherited data automatically

14-20

You might also like