Inheritance Basics Inheritance (with C++) Starting to cover Savitch Chap. 15 � A new class is inherited from an existing class � Existing class is termed the base class – It is the " general " class (a.k.a. superclass, or parent) � New class is termed the derived class – It is the " specific " class (a.k.a. subclass, or child) – Automatically has (i.e., " inherits " ) all of the base class ' s member functions and variables – Can define additional member functions and variables � And override inherited virtual functions (but that ' s a later topic) More OS topics in later weeks (memory concepts, libraries) Inheritance begets hierarchies Base class example: Employee class Employee { � "Is a" relationships public: Employee( ); � Imagine: Employee(string theName, string theSsn); string getName( ) const; class Basketball string getSsn( ) const; is derived from double getNetPay( ) const; void setName(string newName); class Ball void setSsn(string newSsn); void setNetPay(double newNetPay); � Then: void printCheck( ) const; any Basketball is a Ball private: string name; � Reverse not always true: a Ball can be a string ssn; Football , or a Baseball , or … double netPay; }; Writing derived classes Derived class: HourlyEmployee � 3 possibilities for member functions: class HourlyEmployee : public Employee { // Instantly inherits all member functions and variables of class Employee – Inherit – i.e., do nothing public: – Redefine – have new method act differently HourlyEmployee( ); – Define new – add abilities not in base class at all HourlyEmployee(string theName , string theSsn, double theWageRate, double theHours); � 2 possibilities for member variables: void setRate(double newWageRate); – Inherit – though if private, may not directly access/set double getRate( ) const; void setHours(double hoursWorked); – Define new – more data in addition to base class data double getHours( ) const; � Notice: cannot redefine member variables – void printCheck( ); // plan to redefine printCheck function attempts to do so will create " shadow variables " private: double wageRate; – i.e., just creates a new variable with the same name, double hours; effectively hiding the inherited one – usually a mistake };
Derived class constructors A subclass object's composition � A base class constructor is always invoked first � Remember: a derived class definition just – i.e., first task of derived class constructor ' s initialization list defines part of the resulting object – If not done explicitly, base class default constructor will be – The rest of the object is the base class portion called implicitly � Will result in compile error if base class has no default ctor � Need explicit call to use an alternative base class ctor HourlyEmployee – Syntax: BaseClassName(arg1, arg2, …) � Derived Employee example: name: ssn: Employee portion HourlyEmployee::HourlyEmployee(string name, netPay: string number, double rate, double hours) : Employee(name, number), wageRate(rate), wageRate: hours(hours) hours: { } Redefining ≠ overloading Accessing redefined base function � Redefining only applies to a derived class � A redefined base class definition is not " lost " – Same parameter list (i.e., same "signature") Employee jane; – Essentially "re-writes" the same function HourlyEmployee sally; � Overloading can happen in base or derived jane.printCheck(); // Employee function sally.printCheck(); // HourlyEmployee function – Different parameter list – different signature sally.Employee::printCheck(); – Defining a new function with the same name // uses scope resolution to call Employee function! � Recall definition of a signature: � Often done while implmenting derived class – Name(parameter list) – let base function do some of the work – Does not include return type, and '&' ignored Subclass operator= and copy ctor Some functions are not inherited � Although not inherited, a derived class typically � All " normal " functions in the base class are must use the base class ' s versions � e.g., an operator= in class D : public B inherited in the derived class D& D::operator=(const D &right) { � The exceptions ( " abnormal " functions?) : // first call assignment operator of base class to take – Constructors and destructor // care of all the inherited member variables – Copy constructor and assignment operator B::operator=(right); � Compiler generates default versions if you don ' t ... // then set new variables of derived class redefine them in the derived class } � Copy ctor must use base class version too – But remember that can be problematic if pointing to D::D(const D &other) : B(other), ...{ } dynamic memory, so often should redefine
Destructors in derived classes Examples: PFArrayD and …Bak ~mikec/cs32/demos/ SavitchAbsolute_ch14/ � Easy to write if base class dtor is correct � Base class PFArrayD : PFArrayD.h – No need to call base class dtor – because it is – Stores a pointer to a double array on free store called automatically at the end of the derived � Array has a fixed capacity after construction class’s dtor – Has mgr., other functions, plus [] and = ops � So derived class destructors need only � Derived class PFArrayDBak: worry about derived class variables …PFArrayDBak – Has pointer to its own array – can be used to – Usual purpose: release resources allocated backup and restore data in base class ' s array during the object ' s life – Redefines ctors, dtor and operator= – Let base class dtor handle inherited resources Writing derivable classes protected / private inheritance � Always provide a constructor that can be called � Note: rarely used; frankly a little weird with no arguments – Destroys “ is a ” relation of derived class object � Control subclass ' access to member variables and � Protected inheritance – all public members in the functions as appropriate – three choices: base class become protected members in the – public members are accessible to all other classes derived class – private members are not directly accessible to any other class – should be used for most variables, and class SalariedEmployee : protected Employee {…} also appropriate for " helper " functions � Private inheritance – all members in the base class – A third choice is protected member access become private in the derived class � Only subclasses (those derived from this one) can access class SalariedEmployee : private Employee {…} � Some consider it bad OOP practice – violates info hiding Many more inheritance issues Virtual functions – concepts � For instance: Sometimes it is better to use � Virtual: exists in essence though not in fact “ has a ” instead of “ is a ” relationship � Idea is that a virtual function can be “ used ” – Means one class has an object of another class before it is defined – Generally a more flexible design – And it might be defined many, many ways! � Can also do multiple inheritance in C++ � Relates to OOP concept of polymorphism class ClockRadio : public Radio, public AlarmClock; – Associate many meanings to one function – Tricky though (more later, after virtual keyword) � Implemented by dynamic binding � “ Slicing ” and “ upcasts ” – more to come – A.k.a. late binding – happens at run-time
More recommend