Inheritance

"is-a" relationship

Inheritance Hierarchies

Inheritance and Classes

Extending Classes: Time representations

// Military time class
class Time {
        public:
                   Time(int h = 0, int m = 0, int s = 0); // constructor
                    void setTime (int h, int m, int s);       // reset
                    void incrementTime(  );                   // add one second
                    void printTime (  ) const;         
        private:
                    int hours;     // 0 - 23
                    int minutes;   // 0 - 59
                    int seconds;   // 0 - 59
};
 

Time :: Time (int h, int m, int s) : hours (h), minutes (m), seconds (s)

    {} // no code – uses initialization list
 
void Time :: setTime (int h, int m, int s) 
{
hours = h%24;
minutes = m%60;
seconds = s%60;
}
void Time :: increment (  )  // add one second
{
    seconds ++ ;
    if (seconds > 59) {
        seconds = 0;
        minutes ++ ;
        if (minutes > 59) {
            minutes = 0;
            hours ++ ;
            if (hours > 23)
                hours = 0;
        }
   }
}
 
void Time :: printTime ( ) const  // print hh:mm:ss with leading zeroes
{
    if (hours < 10)
        cout << '0';
    cout << hours << ':';
    if (minutes < 10)
       cout << '0';
    cout << minutes << ':';
    if (seconds < 10)
        cout << '0';
    cout << seconds;
}
// ZonedTime is derived from Time
class ZonedTime: public Time  {   // public inheritance; more below
    public:
        enum Zone {EST, CST, MST, PST, EDT, CDT, MDT, PDT};
        ZonedTime(int h = 0, int m = 0, int s = 0, Zone z = EST);
        void setZonedTime (int h, int m, int s, ZoneType z);
        void printZonedTime( ) const;
 private:
        Zone zone;
};

What is included in a (publicly) derived class?

  • ZonedTime objects have all members and member functions of Time objects
  • They also have a private Zone member named zone (specialization)
  • All of Time's public members and functions are available to ZonedTime objects
  • Time's private members and functions are not available to ZonedTime objects

Protected access specification

  • Derived classes do have access to any protected members and functions of base classes
  • If hours, minutes, seconds had been protected instead of private, ZonedTime objects could have accessed these members
  • Potential violation of data encapsulation

Implementation of ZonedTime

Constructors
  • Not inherited (for use on derived class objects)
  • Default constructor still provided if no others implemented
  • At derived class construction, default constructor for base class(es) called first
  • Can use different base constructor with initialization list
  • Derived class constructor must initialize extra (specialized) members

ZonedTime :: ZonedTime (int h, int m, int s, Zone z)
: Time (h, m, s), zone(z) { // no other code necessary }

Member functions

  • Often will call inherited methods on inherited members
  • Must directly handle any specialized members
void ZonedTime :: setZonedTime(int h, int m, int s, Zone z)
{
SetTime (h, m, s);  // on the inherited Time object
zone = z;               // for the specialized Zone member
}

 

void ZonedTime :: printZonedTime ( ) const
{
    static char* zoneString[8] =
    { "EST", "CST", "MST", "PST", "EDT", "CDT", "MDT", "PDT"};
    printTime ( ); // on the inherited Time object
    cout << ' ' << zoneString[zone]; // for the specialized Zone member
}

Assignment operators

ZonedTime& ZonedTime :: operator=(const ZonedTime& rhs)
{
if (this != &rhs)  // same check for self-assignment
    {
        // explicitly call base class = ; not done automatically
        Time::operator= (rhs); // implicit invocation on *this
        zone = rhs.zone;
    }
return *this;
}

Destructors

Using the base and derived classes

void main ( ) 
{
    ZonedTime zt (12, 0, 0); // noon, EST

    zt.printZonedTime ( ); // ZonedTime method
    zt.increment ( ); // an inherited method
    zt.printTime ( ); // just prints hh:mm:ss
    zt.setZonedTime (13, 12, 7, ZonedTime::PST);
    zt.printZonedTime ( ); // ZonedTime method

}

Friendship

  • Not inherited
  • Friend of base class is not automatically friend of derived class
  • Of course, can make it so if necessary

Function Overriding

  • One example of specialization of derived classes
  • Redefine behavior of base class functions for derived classes
  • Redefine function with same signature (return type, name, parameters, const)
  • Different than function overloading (which uses same name but different signature)
  • Can only be done between base and derived classes
  • Provides more transparency to users

Example: override printTime instead of defining printZonedTime

class ZonedTime: public Time  {
  public:
       enum Zone  {EST, CST, MST, PST, EDT, CDT, MDT, PDT};
        ZonedTime(int h = 0, int m = 0, int s = 0, Zone z = EST);
        void setZonedTime (int h, int m, int s, Zone z);
        void printTime( ) const; // function OVERRIDING
  private:
     Zone zone;
};
 
void ZonedTime :: printTime ( ) const
{
// new code for printing hours, minutes, seconds
// or call Time :: printTime( )
// then output the zone
}

 

// main won’t call Time::printTime( ) because it’s “hidden” behind ZonedTime::printTime( )
main ( ) 
{
    ZonedTime zt (12, 0, 0); // noon, EST (default parameter)

    zt.increment ( ); // an inherited method
    zt.printTime ( ); // overridden method
}

Virtual Functions

class Time {
    public:  // other stuff...
                virtual void printTime (  ) const;         
    private: // other stuff...
};

class ZonedTime : public Time {
    public:  // other stuff...
                void printTime (  ) const; //  New implementation will be found at runtime
    private: // other stuff...
};

    Time* t = new ZonedTime(8);
    t -> printTime( );  // calls ZonedTime :: printTime ( )

 

Pure Virtual Functions

  • sometimes a superclass virtual function is just an interface to a subclass implementation
    class Printable {
        public:
                virtual void Print ( ) = 0;  // not implemented ("pure")
        ....                                          //   serves as interface 
    };
    class Time : public Printable {
        public:
                void Print ( );  // Time class implements Printable :: Print ( )
        ...
        };
  • Printable is an abstract base class (serves as interface rather than object)
  • can't instantiate such a class
  • can only instantiate derived classes with all pure virtual functions implemented
  • used when base class has no idea how derived classes can do the job
  • if one is declared, should also declare pure virtual destructor

 

 

 

Types of inheritance

  • We saw public inheritance above
        derived class has no access to private part of base class
        public and protected parts of base class have same access
             specifications in the derived class
  • Also protected inheritance...
        derived class has no access to private part of base class
        public and protected parts of base class become protected members
            of derived class
  • And private inheritance
        derived class has no access to private part of base class
        public and protected parts of base class become private parts
             of derived class
  • Protected and private inheritance rarely used; hide the "is-a" relationship
  • Convenient alternative to aggregation (if only one contained object needed)