Monday, 24 June 2013

C++ : Inheritence

1 Inheritance

Inheritance is a C++ mechanism which provides for code reuse.
A class can be derived from some other class, called the base class. This means that the derived class is a modified or augmented version of the base class.

A derived class can be the base class for another derived class.
Inheritance imposes ISA relationships.


Example of an IS-A relationship


1.1 Syntax
class derived_classname : (public---protected---private) base_class_name
{
.
.
};
The syntax is essentially the same as the usual class syntax, but
the base class is named after the colon (:)


The level of access of the derived class to the base class members is given
as public, protected, or private. In the following, DerivedClass is derived from BaseClass
with public access.

class BaseClass
{
  private:
    int a;

  protected:
    int b;

  public:
    BaseClass();
    virtual ~BaseClass();
    virtual int Foo();
    int Goo();
};

class DerivedClass : public BaseClass
{
    int Foo();
};


1.2 What is Inherited?
The derived class inherits everything from the base class EXCEPT

  • private fields,
  • constructors,
  • the assignment operator
1.3 Access Level
  • The private fields of the base class are NOT inherited by the derived class.
  • The access level determines the maximum level an inherited field will have
    in the derived class. It is a ceiling on the derived class's access to inherited fields.
  • The default access level is private.
  • An access level of public means that the derived class has the same access as the base class to inherited fields (protected remains protected, public remains public). Private fields are NOT inherited.
  • An access level of protected means that the derived class has no greater than protected access to inherited fields (protected remains protected, public becomes protected). Private fields are NOT inherited.
  • An access level of private (the default) means that the derived class has no greater than private access to the inherited fields (protected becomes private, public becomes private). Private fields are NOT inherited.

1.4 Virtual Functions
When a function is declared virtual in the base class, the derived class can override it.

NOTE: "override" is not the same as "overload".
The derived class overrides the definition of a virtual function in the base class simply by re­defining it. An overriding function must have the same argument types and same return type as the function it overrides.


2 Sorted Lists as an Example of Inheritance

The Sorted List class is derived from the List class with public access level.

template <class Etype>
class Sorted_List : public List<Etype>
{
  public:
    Sorted_List() : List() {}
    virtual void Insert( const Etype & X );
    virtual void Insert_As_First_Element( const Etype & X )
      {
        Error( ''Illegal operation for sorted list.'' );
        }
};

It is a good idea to explicitly construct the base class in the constructor for the derived class.
We do so in the initialization part of the definition of Sorted List().
The functions Insert and Insert_As_First_Element are overridden in the derived class Sorted List.
It is usual, but not required to declare, in the derived class, the
overridden functions as virtual. virtual is the default.
Since the base class function Insert_As_First_Element makes no sense for a Sorted List,
it is overriden to return an Error.


Here is the definition of the overridden function Insert

template
void Sorted_List:: Insert( const Etype & X )
{
  for( Node *P = List_Head; P­>Next != NULL; P = P­>Next )
    if( P­>Next­>Element > X )
      break;

    Current_Pos = P;
    List::Insert( X );

}

This first finds the correct insertion point in the list and sets Current Pos there.
Then, it inserts the new element after the node pointed to by Current Pos.
Note that the Insert function used is the one from List, the base class (the scope resolution operator :: causes this to be so).

QUESTION: Suppose the insertion was done as Insert( X )?
ANSWER:


2.1 Example of Use of Sorted List

main ()
{
  List U;
  Sorted_List S;

  S.Insert(5); U.Insert(5);
  S.Insert(2); U.Insert(2);
  S.Insert(9); U.Insert(9);
  S.Insert(1); U.Insert(1);
  cout << S << endl;        // assuming << is overloaded appropriately
  cout << U << endl;
}

will produce the output
1  2  5  9
5  2  9  1

The Insert which got used was the Insert for the class (base or derived) type.
U is of type List, so List::Insert is used.
S is of type Sorted List, so Sorted_List::Insert is used.


3 Virtual Functions and Pointers
A pointer to a base class can be pointed to a derived class instance.

In the following example, L is a pointer to the base class, but
it is actually pointed at a derived class instance.

{
  List *L;                    // L is a pointer to base class
  L = new Sorted_List;  // but points to a derived class
  L­>Insert( 3 );
}

The Insert function used is the one corresponding to the type
of the actual instance L points to. In this case, L is pointing to an
instance of a Sorted_List, so the Insert is Sorted_List::Insert.

The decision about what a pointer will point at cannot necessarily
be made at compile time. Therefore, the decision is made at execution time.

This is called dynamic binding
.
Here is an example which shows how to form an array of pointers to List,
then point the pointers at Lists and Sorted_Lists. The Insert calls take
care of themselves.
{
  List * list_array[2];
  list_array[0] = new List;
  list_array[1] = new Sorted_List;

  for (int i=5; i > 0; i­­)
  {
    list_array[0]­>Insert ( i );
    list_array[1]­>Insert ( i );
  }

  cout << *(list-array[0]) << endl; // output List
  cout << *(list-array[1]) << endl; // output Sorted-List

}

The output is:
5  4  3  2  1
1  2  3  4  5


4 Overload vs. Override

A function is "overloaded" when it has the same name as some other function, but a different argument list. The return type does not matter.

A function is "overridden" when it is a virtual member function of a base class and a derived class redefines it. The overriding and overridden functions must have precisely the same argument list and return type.

No comments:

Post a Comment