1 / 62

Chapter 14

Chapter 14. Inheritance. Learning Objectives. Inheritance Basics Derived classes, with constructors protected: qualifier Redefining member functions Non-inherited functions Programming with Inheritance Assignment operators and copy constructors Destructors in derived classes

mirit
Download Presentation

Chapter 14

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Chapter 14 Inheritance

  2. Learning Objectives • Inheritance Basics • Derived classes, with constructors • protected: qualifier • Redefining member functions • Non-inherited functions • Programming with Inheritance • Assignment operators and copy constructors • Destructors in derived classes • Multiple inheritance

  3. 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 ofgeneral class • And add to it/modify it’s functionality for it’sappropriate use

  4. Inheritance Basics • New class inherited from another class • Base class • "General" class from which others derive • Derived class • New class • Automatically has base class’s: • Member variables • Member functions • Can then add additional member functionsand variables

  5. Derived Classes • Consider example:Class of "Employees" • Composed of: • Salaried employees • Hourly employees • Each is "subset" of employees • Another might be those paid fixed wage eachmonth or week

  6. Interface for the Base Class Employee (Display 14.1) • #ifndef EMPLOYEE_H • #define EMPLOYEE_H • #include <string> • using std::string; • namespace SavitchEmployees • { • class Employee • { • public: • Employee( ); • Employee(string theName, string theSsn); • string getName( ) const; • string getSsn( ) const; • double getNetPay( ) const; • void setName(string newName); • void setSsn(string newSsn); • void setNetPay(double newNetPay); • void printCheck( ) const; • private: • string name; • string ssn; • double netPay; • }; • }//SavitchEmployees • #endif //EMPLOYEE_H //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.

  7. Implementation for the Base Class Employee (Display 14.2; part 1 of 2) • #include <string> • #include <cstdlib> • #include <iostream> • #include "employee.h" • using std::string; • using std::cout; • namespace SavitchEmployees • { • Employee::Employee( ) : name("No name yet"), ssn("No number yet"), netPay(0) • { • //deliberately empty • } • Employee::Employee(string theName, string theNumber) • : name(theName), ssn(theNumber), netPay(0) • { • //deliberately empty • } • string Employee::getName( ) const • { • return name; • } • string Employee::getSsn( ) const • { • return ssn; • } //This is the file: employee.cpp //This is the implementation for the class Employee. //The interface for the class Employee is in the header file employee.h.

  8. Implementation for the Base Class Employee (Display 14.2; part 2 of 2) • double Employee::getNetPay( ) const • { • return netPay; • } • void Employee::setName(string newName) • { • name = newName; • } • void Employee::setSsn(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" • << "Check with the author of the program about this bug.\n"; • exit(1); • } • }//SavitchEmployees //This is the file: employee.cpp //This is the implementation for the class Employee. //The interface for the class Employee is in the header file employee.h.

  9. Derived Classes • Don’t "need" type of generic "employee" • Since no one’s just an "employee" • General concept of employee helpful! • All have names • All have social security numbers • Associated functions for these "basics" aresame among all employees • So "general" class can contain all these"things" about employees

  10. Employee Class • Many members of "employee" class applyto all types of employees • Accessor functions • Mutator functions • Most data items: • SSN • Name • Pay • We won’t have "objects" of this class, however

  11. Employee Class • Consider printCheck() function: • Will always be "redefined" in derived classes • So different employee types can havedifferent checks • Makes no sense really for "undifferentiated"employee • So function printCheck() in Employee classsays just that • Error message stating "printCheck called forundifferentiated employee!! Aborting…"

  12. Deriving from Employee Class • Derived classes from Employee class: • Automatically have all member variables • Automatically have all member functions • Derived class said to "inherit" membersfrom base class • Can then redefine existing membersand/or add new members

  13. Display 14.3 Interface for the Derived Class HourlyEmployee (1 of 2)

  14. Display 14.3 Interface for the Derived Class HourlyEmployee (2 of 2)

  15. Display 14.4 Interface for the Derived Class SalariedEmployee • #ifndef SALARIEDEMPLOYEE_H • #define SALARIEDEMPLOYEE_H • #include <string> • #include "employee.h" • using std::string; • namespace SavitchEmployees • { • class SalariedEmployee : public Employee • { • public: • SalariedEmployee( ); • SalariedEmployee (string theName, string theSsn, • double theWeeklySalary); • double getSalary( ) const; • void setSalary(double newSalary); • void printCheck( ); • private: • double salary;//weekly • }; • }//SavitchEmployees • #endif //SALARIEDEMPLOYEE_H //This is the header file salariedemployee.h. //This is the interface for the class SalariedEmployee.

  16. HourlyEmployee Class Interface • Note definition begins same as any other • #ifndef structure • Includes required libraries • Also includes employee.h! • And, the heading:class HourlyEmployee : public Employee{ … • Specifies "publicly inherited" from Employeeclass

  17. HourlyEmployee Class Additions • Derived class interface only lists new or"to be redefined" members • Since all others inherited are already defined • i.e.: "all" employees have ssn, name, etc. • HourlyEmployee adds: • Constructors • wageRate, hours member variables • setRate(), getRate(), setHours(), getHours()member functions

  18. HourlyEmployee Class Redefinitions • HourlyEmployee redefines: • printCheck() member function • This "overrides" the printCheck() functionimplementation from Employee class • It’s definition must be in HourlyEmployeeclass’s implementation • As do other member functions declared inHourlyEmployee’s interface • New and "to be redefined"

  19. Inheritance Terminology • Common to simulate family relationships • Parent class • Refers to base class • Child class • Refers to derived class • Ancestor class • Class that’s a parent of a parent … • Descendant class • Opposite of ancestor

  20. Constructors in Derived Classes • Base class constructors are NOT inherited in derived classes! • But they can be invoked within derived classconstructor • Which is all we need! • Base class constructor must initialize allbase class member variables • Those inherited by derived class • So derived class constructor simply calls it • "First" thing derived class constructor does

  21. Derived Class Constructor Example • Consider syntax for HourlyEmployeeconstructor: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

  22. Another HourlyEmployee Constructor • A second constructor:HourlyEmployee::HourlyEmployee() : Employee(), wageRate(0), hours(0){ //Deliberately empty} • Default version of base class constructoris called (no arguments) • Should always invoke one of the baseclass’s constructors

  23. Constructor: No Base Class Call • Derived class constructor should alwaysinvoke 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){ }

  24. Implementation for the Derived Class HourlyEmployee (Display14.5 1/2) //This is the file: hourlyemployee.cpp //This is the implementation for the class HourlyEmployee. //The interface for the class HourlyEmployee is in //the header file hourlyemployee.h. • #include <string> • #include <iostream> • #include "hourlyemployee.h" • using std::string; • using std::cout; • using std::endl; • namespace SavitchEmployees • { • HourlyEmployee::HourlyEmployee( ) : Employee( ), wageRate(0), hours(0) • { • //deliberately empty • } • HourlyEmployee::HourlyEmployee(string theName, string theNumber, • double theWageRate, double theHours) • : Employee(theName, theNumber), wageRate(theWageRate), hours(theHours) • { • //deliberately empty • } • void HourlyEmployee::setRate(double newWageRate) • { • wageRate = newWageRate; • } • double HourlyEmployee::getRate( ) const • { • return wageRate; • }

  25. Implementation for the Derived Class HourlyEmployee (Display14.5 2/2) • void HourlyEmployee::setHours(double hoursWorked) • { • hours = hoursWorked; • } • double HourlyEmployee::getHours( ) const • { • return hours; • } • void HourlyEmployee::printCheck( ) • { • setNetPay(hours * wageRate); • 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 << "Hourly Employee. \nHours worked: " << hours • << " Rate: " << wageRate << " Pay: " << getNetPay( ) << endl; • cout << "_________________________________________________\n"; • } • }//SavitchEmployees

  26. Implementation for the Derived Class SalariedEmployee (Display14.6 1/2) //This is the file salariedemployee.cpp //This is the implementation for the class SalariedEmployee. //The interface for the class SalariedEmployee is in //the header file salariedemployee.h. • #include <iostream> • #include <string> • #include "salariedemployee.h" • using std::string; • using std::cout; • using std::endl; • namespace SavitchEmployees • { • SalariedEmployee::SalariedEmployee( ) : Employee( ), salary(0) • { • //deliberately empty • } • SalariedEmployee::SalariedEmployee(string newName, string newNumber, • double newWeeklyPay) • : Employee(newName, newNumber), salary(newWeeklyPay) • { • //deliberately empty • } • double SalariedEmployee::getSalary( ) const • { • return salary; • }

  27. Implementation for the Derived Class SalariedEmployee (Display14.6 2/2) • 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: " • << salary << endl; • cout << "_________________________________________________\n"; • } • }//SavitchEmployees

  28. Pitfall: Base Class Private Data • Derived class "inherits" private membervariables • But still cannot directly access them • Not even through derived class memberfunctions! • Private member variables can ONLY beaccessed "by name" in member functions of the class they’re defined in

  29. Pitfall: Base Class Private Member Functions • Same holds for base class member functions • Cannot be accessed outside interface andimplementation of base class • Not even in derived class member function definitions

  30. Pitfall: Base Class Private Member Functions Impact • Larger impact here vs. member variables • Member variables can be accessed indirectlyvia accessor or mutator member functions • Member functions simply not available • This is "reasonable" • Private member functions should be simply"helper" functions • Should be used only in class they’re defined

  31. The protected: Qualifier • New classification of class members • Allows access "by name" in derived class • But nowhere else • Still no access "by name" in other classes • In class it’s defined  acts like private • Considered "protected" in derived class • To allow future derivations • Many feel this "violates" information hiding

  32. Self-Test Exercise 1 Is the following program legal (assuming appropriate #include and using directives are added)? • void showEmployeeData(const Employee object); • int main() • { • HourlyEmployee joe(“Mighty Joe”, “123-45-6789”, 20.50, 40); • SalariedEmployee bass(“Mr. Big Shot”, “987-65-4321”, 10500.50); • showEmplyee(joe); • showEmplyee(boss); • return 0; • } • void showEmployeeData(const Employee object) • { • cout << “Name: ” << object.getName() << endl; • cout << “Social Security Number: ” << object.getSsn() << endl; • } Yes. You can plug in an object of a derived class for a parameter of the base class type. An HourlyEmployee is an Employee. A SalariedEmployee is an Employee.

  33. Self-Test Exercise 2 Given a definition for a class SmartBut that is a derived class of the base class Smart given below. Do not bother with #include directives or namespace details. • class Smart • { • public: • Smart(); • void printAnswer() const; • protected: • int a; • int b; • }; This class should have an additional data field, crazy, of type bool; one additional member function that takes no arguments and returns a value of type bool; and suitable constructors. The new function is named isCrazy. You do not need to give any implementations, just the class definition. • class Smart:public Smart • { • public: • SmartBut(); • SmartBut(int newA, int newB, bool newCrazy); • bool isCrazy() const; • protected: • bool crazy; • };

  34. Self-Test Exercise 3 Is the following a legal definition of the member function isCrazy in the derived class SmartBut discussed in Self-Test Exercise 2? Explain you answer. (Remember, the question asks if it is legal, not if it is a sensible definition.) • bool SmartBut::isCrazy() const • { • if (a > b) return crazy; • else return true; • } It is legal because a and b are marked protected in the base class Smart and so they can be accessed by name in a derived class. If a and b had instead been marked private, then this would be illegal.

  35. Redefinition of Member Functions • Recall interface of derived class: • Contains declarations for new member functions • Also contains declarations for inheritedmember functions to be changed • Inherited member functions NOT declared: • Automatically inherited unchanged • Implementation of derived class will: • Define new member functions • Redefine inherited functions as declared

  36. Using Derived Classes SAMPLE DIALOGUE Check for Mighty Joe for 40 hours. --------------------------------------------------------------- Pay to the order of Mighty Joe The sum of 820 Dollars --------------------------------------------------------------- Check Stub: NOT NEGOTIABLE Employee Number: 123-45-6789 Hourly Employee. Hours worked: 40 Rate: 20.5 Pay: 820 --------------------------------------------------------------- Check for Mr. Big Shot --------------------------------------------------------------- Pay to the order of Mr. Big Shot The sum of 10500.5 Dollars --------------------------------------------------------------- Check Stub: NOT NEGOTIABLE Employee Number: 987-65-4321 Salaried Employee. Regular Play: 10500.5 --------------------------------------------------------------- • #include <iostream> • #include "hourlyemployee.h" • #include "salariedemployee.h" • using std::cout; • using std::endl; • using SavitchEmployees::HourlyEmployee; • using SavitchEmployees::SalariedEmployee; • 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; • }

  37. 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

  38. A Function’s Signature • Recall definition of a "signature": • Function’s name • Sequence of types in parameter list • Including order, number, types • Signature does NOT include: • Return type • const keyword • &

  39. Accessing Redefined Base Function • When redefined in derived class, baseclass’s definition not "lost" • Can specify it’s use:Employee JaneE;HourlyEmployee SallyH;JaneE.printCheck(); calls Employee’s printCheck functionSallyH.printCheck(); calls HourlyEmployee printCheck functionSallyH.Employee::printCheck(); Calls Employee’s printCheck function! • Not typical here, but useful sometimes

  40. Functions Not Inherited • All "normal" functions in base class areinherited in derived class • Exceptions: • Constructors (we’ve seen) • Destructors • Copy constructor • But if not defined, generates "default" one • Recall need to define one for pointers! • Assignment operator • If not defined  default

  41. Self-Test Exercise 4 The class SalariedEmployee inherits both of the functions getName and printCheck (among other things) from the base class Employee, yet only the function declaration for the function printCheck is given in the definition of the class SalariedEmployee. Why isn’t the function declaration for the function getName given in the definition of SalariedEmployee? The declaration for the function getName is not given in the definition of SalariedEmployee because it is not redefined in the class Salaried Employee. It is inherited unchanged from the base class Employee.

  42. Self-Test Exercise 5 Given a definition for a class TitledEmployee that is a derived class of the base class SalariedEmployee given in Display 14.4. The class TitledEmployee has one additional member variable of type string called title. It also has two additional member functions: getTitle, which takes one argument of type string, and setTitle, which is a void function that takes one argument of type string. It also redefines the member function setName. You do not need to give any implementations, just the class definition. However, do give all needed #include directives and all using namespace directives. Place the class TitledEmployee in the namespace SavitchEmployees. • #include <iostream> • #include “salariedemployee.h” • Using namespace std; • Namespace SavitchEmployees • { • class TitledEmployee:public SalariedEmployee • { • public: • TitledEmployee(); • TitledEmployee(string theNmae, string theTitle, string theSsn, double the Salary); • string getTitle() const; • void setTitle(string theTitle); • void setName(string theName); • private: • string title; • }; • };

  43. Self-Test Exercise 6 Give the definitions of the constructors for the class TitledEmployee that you gave as the answer to Self-Test Exercise 5. Also, give the redefinition of the member function setName. The function setName should insert the title into the name. Do not bother with #include directives or namespace details. • Namespace SavitchEmployees • { • TitledEmployee:TitledEmployee() • :SalariedEmployee(), title(“No title yet”) • { • //deliberately empty • } • TitledEmployee:TitledEmployee(string theNmae, string theTitle, string theSsn, double the Salary) • :SalariedEmployee(theName, theSsn, theSalary), title(theTitle) • { • //deliberately empty • } • void TitledEmployee:setName(string theName) • { • Employee::setName(title+theName); • } • };

  44. Self-Test Exercise 7 You know that an overloaded assignment operator and a copy constructor are not inherited. Does this mean that if you do not define an overloaded assignment operator or a copy constructor for a derived class, then that derived class will have no assignment operator and no copy constructor? No. If you do not define an overloaded assignment operator or a copy constructor for a derived class, then a default assignment operator and a default copy constructor will be defined for the derived class. However, if the class involves pointers, dynamic arrays, or other dynamic data, then it is almost certain that neither the default assignment operator not the default copy constructor will behave as you want them to.

  45. Assignment Operators and Copy Constructors • Recall: overloaded assignment operators and copy constructors NOT inherited • But can be used in derived class definitions • Typically MUST be used! • Similar to how derived class constructorinvokes base class constructor

  46. Assignment Operator Example • Given "Derived" is derived from "Base":Derived& Derived::operator =(const Derived & rightSide){ Base::operator =(rightSide); …} • Notice code line • Calls assignment operator from base class • This takes care of all inherited member variables • Would then set new variables from derivedclass…

  47. Copy Constructor Example • Consider:Derived::Derived(const Derived& Object) : Base(Object), …{…} • After : is invocation of base copy constructor • Sets inherited member variables of derivedclass object being created • Note Object is of type Derived; but it’s also oftype Base, so argument is valid

  48. 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 no need for explicit call • So derived class destructors need only beconcerned with derived class variables • And any data they "point" to • Base class destructor handles inherited dataautomatically

  49. Destructor Calling Order • Consider:class B derives from class Aclass C derives from class B A  B  C • When object of class C goes out of scope: • Class C destructor called 1st • Then class B destructor called • Finally class A destructor is called • Opposite of how constructors are called

  50. Display 14.8 Interface for the Base Class PFArrayD • void emptyArray( ); • //Resets the number used to zero, effectively emptying the array. • double& operator[](int index); • //Read and change access to elements 0 through numberUsed - 1. • PFArrayD& operator =(const PFArrayD& rightSide); • ~PFArrayD( ); • protected: • double *a; //for an array of doubles. • int capacity; //for the size of the array. • int used; //for the number of array positions currently in use. • }; • #endif //PFARRAYD_H • #ifndef PFARRAYD_H • #define PFARRAYD_H • class PFArrayD • { • public: • PFArrayD( ); • //Initializes with a capacity of 50. • PFArrayD(int capacityValue); • PFArrayD(const PFArrayD& pfaObject); • void addElement(double element); • //Precondition: The array is not full. • //Postcondition: The element has been added. • bool full( ) const; • //Returns true if the array is full, false otherwise. • int getCapacity( ) const; • int getNumberUsed( ) const;

More Related