Thursday 19 December 2013

Inheritance

One of the most important concepts in object-oriented programming is that of inheritance. Inheritance allows us to define a class in terms of another class, which makes it easier to create and maintain an application. This also provides an opportunity to reuse the code functionality and fast implementation time.
When creating a class, instead of writing completely new data members and member functions, the programmer can designate that the new class should inherit the members of an existing class. This existing class is called the base class, and the new class is referred to as the derived class.
The idea of inheritance implements the is a relationship. 
For example, mammal IS-A animal, dog IS-A mammal hence dog IS-A animal as well and so on.

-> Just like abstraction is closely related with generalization, the inheritance is closely related with specialization. It is important to discuss those two concepts together with generalization to better understand and to reduce the complexity.
->One of the most important relationships among objects in the real world is specialization, which can be described as the “is-a” relationship. When we say that a dog is a mammal, we mean that the dog is a specialized kind of mammal. It has all the characteristics of any mammal (it bears live young, nurses with milk, has hair), but it specializes these characteristics to the familiar characteristics of canis domesticus. A cat is also a mammal. As such, we expect it to share certain characteristics with the dog that are generalized in Mammal, but to differ in those characteristics that are specialized in cats.
->The specialization and generalization relationships are both reciprocal and hierarchical. Specialization is just the other side of the generalization coin: Mammal generalizes what is common between dogs and cats, and dogs and cats specialize mammals to their own specific subtypes.


Purpose Of Inheritance:
  1. Code Re-usability (40 %)
  2. Method Overriding (i.e. Run Time Poymorphism) using virtual keyword (60 %).

Base & Derived Classes:

A class can be derived from more than one classes, which means it can inherit data and functions from multiple base classes. To define a derived class, we use a class derivation list to specify the base class(es). A class derivation list names one or more base classes and has the form:
class derived-class: access-specifier base-class

Where access-specifier is one of public, protected, or private, and base-class is the name of a previously defined class. If the access-specifier is not used, then it is private by default.
Consider a base class Shape and its derived class Rectangle as follows:
#include <iostream>
 
using namespace std;

// Base class
class Shape 
{
   public:
      void setWidth(int w)
      {
         width = w;
      }
      void setHeight(int h)
      {
         height = h;
      }
   protected:
      int width;
      int height;
};

// Derived class
class Rectangle: public Shape
{
   public:
      int getArea()
      { 
         return (width * height); 
      }
};

int main(void)
{
   Rectangle Rect;
 
   Rect.setWidth(5);
   Rect.setHeight(7);

   // Print the area of the object.
   cout << "Total area: " << Rect.getArea() << endl;

   return 0;
}
When the above code is compiled and executed, it produces the following result:
Total area: 35

Access Control and Inheritance:

A derived class can access all the non-private members of its base class. Thus base-class members that should not be accessible to the member functions of derived classes should be declared private in the base class.
We can summarize the different access types according to who can access them in the following way:
Access
public
protected
private
Same class
yes
yes
yes
Derived classes
yes
yes
no
Outside classes
yes
no
no
A derived class inherits all base class methods with the following exceptions:
  • Constructors, destructors and copy constructors of the base class.
  • Overloaded operators of the base class.
  • The friend functions of the base class.

When deriving a class from a base class, the base class may be inherited through public, protected orprivate inheritance. The type of inheritance is specified by the access-specifier as explained above.
We hardly use protected or private inheritance, but public inheritance is commonly used. While using different type of inheritance, following rules are applied:
  • Public Inheritance: When deriving a class from a public base class, public members of the base class become public members of the derived class and protected members of the base class become protected members of the derived class. A base class's private members are never accessible directly from a derived class, but can be accessed through calls to the publicand protected members of the base class.
  • Protected Inheritance: When deriving from a protected base class, public and protectedmembers of the base class become protected members of the derived class.
  • Private Inheritance: When deriving from a private base class, public and protected members of the base class become private members of the derived class.
What is inherited?

When inheritance is done, various links and tables (index, virtual etc) are created which are used to provide the accessibility of the members of the base class in derived class and in other class hierarchy. This means saying “public members are inherited” is better to say as “public members become accessible”.
A derived class inherits every member of a base class except:
  • its constructor and its destructor
  • its friends
  • its operator=() members

Types of Inheritance

There are five different inheritances supported in C++:
  • (1) Simple / Single
  • (2) Multilevel
  • (3) Hierarchical
  • (4) Multiple
  • (5) Hybrid














Multiple Inheritances:

A C++ class can inherit members from more than one class and here is the extended syntax:
class derived-class: access baseA, access baseB....
Where access is one of public, protected, or private and would be given for every base class and they will be separated by comma as shown above. Let us try the following example:

#include <iostream>
 
using namespace std;

// Base class Shape
class Shape 
{
   public:
      void setWidth(int w)
      {
         width = w;
      }
      void setHeight(int h)
      {
         height = h;
      }
   protected:
      int width;
      int height;
};

// Base class PaintCost
class PaintCost 
{
   public:
      int getCost(int area)
      {
         return area * 70;
      }
};

// Derived class
class Rectangle: public Shape, public PaintCost
{
   public:
      int getArea()
      { 
         return (width * height); 
      }
};

int main(void)
{
   Rectangle Rect;
   int area;
 
   Rect.setWidth(5);
   Rect.setHeight(7);

   area = Rect.getArea();
   
   // Print the area of the object.
   cout << "Total area: " << Rect.getArea() << endl;

   // Print the total cost of painting
   cout << "Total paint cost: $" << Rect.getCost(area) << endl;

   return 0;
}
When the above code is compiled and executed, it produces the following result:
Total area: 35
Total paint cost: $2450

Execution order of the constructor and destructor in inheritance.

It is sometimes the case that classes are derived from other classes, which are themselves derived from other classes. For example:


































class A
{
public:
    A()
    {
        cout << "A" << endl;
    }
};

class B: public A
{
public:
    B()
    {
        cout << "B" << endl;
    }
};

class C: public B
{
public:
    C()
    {
        cout << "C" << endl;
   }
}; 


class D: public C
{
public:
    D()
    {
        cout << "D" << endl;
    }
};

Remember that C++ always constructs the “first” or “most base” class first. It then walks through the inheritance tree in order and constructs each successive derived class.
Here’s a short program that illustrates the order of creation all along the inheritance chain.















int main()
{
    cout << "Constructing A: " << endl;
    A cA;

    cout << "Constructing B: " << endl;
    B cB;

    cout << "Constructing C: " << endl;
    C cC;

    cout << "Constructing D: " << endl;
    D cD;
}
This code prints the following:
Constructing A:
A
Constructing B:
A
B
Constructing C:
A
B
C
Constructing D:
A
B
C
D

Note:

Base class constructors and derived class destructors are called first


Basically, it's a test to see if you know in what order the constructors and destructors will be called when a program deals with inheritance. 

class Base
{
  public:

  Base ( )
  {
    cout << "Inside Base constructor" << endl;
  } 

  
  ~Base ( )
  {
    cout << "Inside Base destructor" << endl;
  } 

};

class Derived : public Base
{

  public:

  Derived  ( )
  {
    cout << "Inside Derived constructor" << endl;
  } 

  ~Derived ( )
  {
    cout << "Inside Derived destructor" << endl;
  } 

};

void main( )
{
  Derived x;
}
In the code above, when the object "x" is created, first the Base class constructor is called, and after that the Derived class constructor is called. Because the Derived class inherits from the Base class, both the Base class and Derived class constructors will be called when a Derived class object is created.
When the main function is finished running, the object x's destructor will get called first, and after that the Base class destructor will be called.
So, here is what the output of the code above would look like:
Inside Base constructor
Inside Derived constructor
Inside Derived destructor
Inside Base destructor


Note:
Common Interview Question: Are private class members inherited to the derived class?

Ans: Yes, the private members are also inherited in the derived class but we will not be able to access them. Trying to access a private base class member in the derived class will report a compile time error.
class A
{
public :
void fun1 ()
{
}
private:
 void fun2 ()
{
}
};

class B:  public A
{
};

void main ()
{
B B1 = new B ();
B1.fun1 ();
//Error, Cannot access private member fun2
//B1.fun2 ();
}
}

Method Hiding and Inheritance We will look at an example of how to hide a method in C++. The Parent class has a write () method which is available to the child class. In the child class I have created a new write () method. So, now if I create an instance of child class and call the write () method, the child class write () method will be called. The child class is hiding the base class write () method. This is called method hiding.

If we want to call the parent class write () method, we would have to type cast the child object to Parent type and then call the write () method as shown in the code snippet below.

class Parent
{
    public:
 void write ()
    {
        cout<< "Parent Class write method";
    }
};
class Child: public Parent
{
    public:
  void write ()
    {
       cout<<"Child Class write method";
    }
   };

    void main ()
    {
        Child c1 = new Child ();
        c1.write ();
        //Type caste c1 to be of type Parent and call write () method
        ((Parent) C1).write ();
    }

UpCasting:

Upcasting is using the Super class's reference or pointer to refer to a Sub class's object. Or we can say that, the act of converting a Sub class's reference or pointer into its Super class's reference or pointer is called Upcasting.





















class Super
{
 int x;


public:

void funBase() { cout << "Super function"; }

};

class Sub : public Super


{
int y;
};


int main()


{


Super* ptr; // Super class pointer


Sub obj;


ptr = &obj;


Super &ref; // Super class's reference


ref=obj;








}

The opposite of Upcasting is Downcasting, in which we convert Super class's reference or pointer into derived class's reference or pointer. We will study more about Downcasting later

Functions that are never Inherited

1. Constructors and Destructors are never inherited and hence never overrided.
2. Also, assignment operator = is never inherited. It can be overloaded but can't be inherited by sub class.

Inheritance and Static Functions

  1. They are inherited into the derived class.
  2. If you redefine a static member function in derived class, all the other overloaded functions in base class         are hidden.
  3. Static Member functions can never be virtual. We will study about Virtual in coming topics.


No comments: