Inheritance
“the mechanism by which one class acquires
      the properties of another class”
           Arrange concepts into an
            inheritance hierarchy
• Concepts at higher levels are more general
• Concepts at lower levels are more specific (inherit
  properties of concepts at higher levels)
                                        Vehicle
                 Wheeled vehicle                  Boat
           Car                Bicycle
  2-door             4-door
          C++ and inheritance
• The language mechanism by which one class
  acquires the properties (data and operations)
  of another class
• Base Class (or superclass): the class being
  inherited from
• Derived Class (or subclass): the class that
  inherits
     Advantages of inheritance
• When a class inherits from another class,
  there are three benefits:
• (1) You can reuse the methods and data of
  the existing class
  (2) You can extend the existing class by
  adding new data and new methods
  (3) You can modify the existing class by
  overloading its methods with your own
  implementations
Deriving One Class from Another
       Deriving One Class from Another (cont’d)
• Define a new class CountedQue from QueType
  such that it has a new data member (length) that
  records the number of items in the queue
   template<class ItemType>
   class CountedQue : public QueType<ItemType> {
     public:
      CountedQue();
      void Enqueue (ItemType newItem);
      void Dequeue (ItemType& item);
      int LengthIs() const;
     private:
      int length;
   };
   Inheritance and accessibility
• A class inherits the behavior of another
  class and enhances it in some way
• Inheritance does not mean inheriting
  access to another class’ private members
Rules for building a class hierarchy
• Derived classes are special cases of base classes
• A derived class can also serve as a base class for new
  classes.
• There is no limit on the depth of inheritance allowed
  in C++ (as far as it is within the limits of your
  compiler)
• It is possible for a class to be a base class for more
  than one derived class
                     Modifying class behavior
template<class ItemType>
void CountedQue<ItemType>::Enqueue(ItemType newItem)
{
    length++;
    QueType<ItemType>::Enqueue(newItem);
}
template<class ItemType>
void CountedQue<ItemType>::Dequeue(ItemType& item)
{
    length--;
    QueType<ItemType>::Dequeue(item);
}
template<class ItemType>
int CountedQue<ItemType>::LengthIs() const
{
    return length;
}
// class constructor
template<class ItemType>
CountedQue<ItemType>::CountedQue() : QueType<ItemType>()
{
 length=0;
}
                 Polymorphism
• Any code you write to manipulate a base class will
  also work with any class derived from the base class.
• C++ general rule for passing objects to a function:
      “the actual parameters and their corresponding
  formal         parameters must be of the same type”
• With inheritance, C++ relaxes this rule:
     “the type of the actual parameter can be a class
     derived from the class of the formal parameter”
                 An example
  template<class ItemType>
  void Test(QueType& q, ItemType item)
  {
  q.Enqueue(item);
    ....
  }
• Any object of a class derived from QueType can be
  passed to the function !!
• Which Enqueue() function should be used? (the
  compiler does not know that at compile time)
     Static vs. dynamic binding
• Static Binding: the determination of which
  method to call at compile time
• Dynamic Binding: the determination of which
  method to call at run time
              Virtual Functions
•   C++ uses virtual functions to implement run-
    time binding.
•   To force the compiler to generate code that
    guarantees dynamic binding, the word virtual
    should appear before the function
    declaration in the definition of the base class.
           Queue Implementation
template<class ItemType>              private:
class QueueType {                        int front;
 public:
   QueueType(int);
                                         int rear;
   QueueType();                          ItemType* items;
   ~QueueType();                         int maxQue;
   void MakeEmpty();                  };
   bool IsEmpty() const;
   bool IsFull() const;
   virtual void Enqueue(ItemType);
   virtual void Dequeue(ItemType&);
      Virtual Functions (cont.)
• Rules for static/dynamic binding:
  1) If the member function of the base class is not
    a virtual function, the type of the formal
    parameter determines which function to call.
  2) If the member function of the base class is a
    virtual function, the type of the actual
    parameter determines which function to call.
                       An example
class ItemType {
 public:
   ...
   virtual bool operator<(ItemType) const;
 private: protected:
   StrType lastName;
};
bool ItemType::operator<(ItemType item) const
{
    int result;
    result = strcmp(lastName, item.lastName);
    if(result < 0)
      return true;
    else
      return false;
}
Let's derive a new class from it:
class NewItemType : public ItemType {
  public:
   ...
   bool operator<(NewItemType) const;
  private:
   StrType firstName;
};
Let's derive a new class from it: (cont.)
bool NewItemType::operator<(NewItemType item) const
{
    int result;
    result = strcmp(lastName, item.lastName);
    if(result < 0)
      return true;
    else if(result > 0)
      return false;
    else { // same last name
      result = strcmp(firstName, item.firstName);
      if(result < 0)
        return true;
      else
        return false;
 }
}
Let's assume that the client program
includes the following function:
void PrintResult(ItemType& first, ItemType& second)
{
 if(first < second) // first.operator<(second)
   cout << "First comes before second";
 else
   cout << "First does not come before second";
}
Let's assume that the client program
executes the following code:
        ItemType item1, item2;
        NewItemType item3, item4;
         ....
        PrintResult(item1, item2);
        PrintResult(item3, item4);
       Protected class members
• Derived classes cannot access the private data
  of the base class
• Declaring methods and data of the base class
  as protected (instead of private) allows
  derived classes to access them
• Objects outside the class, however, cannot
  access them (same as private)
     Warning: call by reference
         vs. call by value
• If the object of the derived class is passed by
  reference, everything works fine.
• If the object of the derived class is passed by
  value, only the sub-object of the base class is
  passed to the function (slicing problem)!!
      Protected and Private Inheritance
  class X : protected Y {             Y
     ...
  };                                          X
• With protected inheritance, public and protected
  members of Y become protected in X (i.e., classes
  derived from X inherit the public members of Y as
  protected)
• With private inheritance, public and protected
  members of Y become private in X (i.e., classes
  derived from X inherit the public members of Y as
  private)
• Default inheritance: private
     Constructors and destructors
• You cannot override a base class constructor with a
  derived class constructor (rather, the derived class
  constructor calls the base class constructor first)
• All base class destructors should be declared virtual
• Virtual destructors are called in reverse order from
  the constructors for derived class objects
       Multiple Inheritance
• Derived classes can inherit from more than
  one base classes
                         X     (base for Y)
                         Y     (base for Z)
                         Z
                    Example
Define a new class LookAheadStack that is
derived from class StackType.
(1) A look-ahead stack differs from the standard stack
only in the push operation.
(2) An item is added to the stack by the push method
only if its different from the top stack element.
template<class ItemType>
struct NodeType;
template<class ItemType>
class StackType {
       public:
         StackType();
         ~StackType();
         void MakeEmpty();
         bool IsEmpty() const;
         bool IsFull() const;
         void Push (ItemType);
         void Pop(ItemType&);
       private:
         NodeType<ItemType>* topPtr;
};
template<class ItemType>
class LookAheadStack : public StackType<ItemType>
{
   public:
         void Push(ItemType);
         LookAheadStack();
         ~LookAheadStack();
};
b) Implement the new push function and the
   derived class’ constructor.
template<class ItemType>
void LookAheadStack <ItemType>::Push(ItemType newItem)
{
  ItemType item;
    if ( !StackType<ItemType>::IsEmpty() ) {
       StackType<ItemType>::Pop(item);
       StackType<ItemType>::Push(item);
       if (item != newItem)
          StackType<ItemType>::Push(newItem);
    }
    else
       StackType<ItemType>::Push(newItem);
}
Constructor:
template<class ItemType>
LookAheadStack <ItemType>:: LookAheadStack():StackType()
{
}
c) Which functions and from which class
   should be declared as virtual?
The functions that should be declared as
virtual are:
     Push from base class (StackType)
     Destructor from base class (StackType)