Inheritance.

Object oriented languages such as C++, Java, C#, etc, allow us to build a new class by deriving it from an already existing class. This mechanism is called inheritance, and the derived class is said to be inherited from the original class.

To illustrate the idea of inheritance, let's assume that we need to develop a project that should work with students, graduate students, professors, and alumni. We need to keep slightly different set of data for a member each of these groups, but all of them should have:

If we create a separate class for each of these groups, then all the classes will be having the same data members to store the values listed above, and very similar code for accessing them. To avoid unnecessary duplication we can create class Person that contains all common features:
class Person {
   private:
      String name;
      String address;
      String phone;
      String ID;
      int    SSN;
   public:
      Person();
      ~Person();
      void PrintName();
      ...
};
And make this class to be the base class for all other classes.

Syntax

To derive a new class from already existing class, we use the following syntax:
class new_class : [access] base_class {
   ...
};
where access is one of the following keywords: For example, we can derive a new class Student from the class Person, and a new class GradStudent from the class Student:
class Student : public Person {
   private:
      Course courses_taken[];
      String major;
      String minor;
   protected:
      bool keep_privately;
   public:
      Student();
      ~Student();
      float GPA();
      ...
};

class GradStudent : public Student {
   private:
      Course     grad_courses[];
      Professor *advisor;
   public:
      GradStudent();
      ~GradStudent();
      void PrintAdvisor();
      ...
};
If we defined the classes Person, Student, and GradStudent as shown, the we say that

A derived class inherits all public and protected members from its base class excluding:

All other data members and methods become members of the derived class. For example, we can use method PrintName() of the class Person, or method GPA() of the class Student as methods of an object of the GradStudent class:
GradStudent stud;
stud.PrintName();
cout<<stud.GPA();
Please note that:

UML uses the following notation for derived classes:

UML diagram for derived classes
Please note that UML uses

Access control

We have already seen a new keyword protected in a class definition. Thus, a class definition has the following syntax:
class Name {
   public:
      declaration of public (visible) members
   protected:
      declaration of protected members
   private:
      declaration of private members
};
We know that public members are visible from outside the class and that private members are visible only from inside and for friends of the class. In the absence of inheritance the protected members behave exactly like private members; that is, they are not visible outside. However, there is a difference between private and protected members if there is a class derived from the class under consideration. Namely, programmers can access the protected members of the base class inside the derived class.

For example, if we have the BaseClass class defined as

class BaseClass {
   public:
      int number;
   protected:
      char letter;
   private:
      bool test;
};
and the class DerivedClass defined as
class DerivedClass : public BaseClass {
   public:
      int another_number;
      void Print();
};
then inside the method Print() we can access the following variables: data member test is also inherited by the derived class, but it cannot be accessed. If we are outside of the derived class, then we can only access data members number and another_number:
DerivedClass object;
object.number = 10;          // OK - it's public
object.another_number = 0;   // OK - it's public

However, if we change the access mode in the definition of the derived class from public to protected:

class DerivedClass : protected BaseClass {
   public:
      int another_number;
      void Print();
};
then data member number inherited by the derived class is no longer public, it is protected and cannot be accessed from outside the class:
DerivedClass object;
object.another_number = 0;   // OK - it's public
object.number = 10;          // ERROR - it's protected
If we have a class derived from the class DerivedClass, though. This new class will be able to access this variable number.

Constructors and destructors for derived classes

As we mentioned above, a derived class does not inherit the constructors of its base class. However, since the derived class is a specialization of the base class (that is, it inherits all characteristics of the base class), the default constructor of the base class is automatically invoked when a derived class object is created. For example, for the following code:
#include <iostream>
using namespace std;

class BaseClass {
  public:  BaseClass() { cout<<"Base class constructor\n"; };
};

class DerivedClass : public BaseClass {
  public:  DerivedClass() { cout<<"Derived class constructor\n"; };
};

void main()
{
   DerivedClass object;
}
the output would be
Base class constructor
Derived class constructor

If the base class has other constructors besides the default one and we would like to use any of them instead of automatically invoked default one, we can do so by specifying the exact constructor (by passing it the right arguments) in the initialization list. For example, if in the previous code the BaseClass also has a constructor like:

BaseClass(string word) { cout<<word<<"  ==> Base class constructor\n"; };
then this constructor can be explicitly invoked in the DerivedClass constructor by
DerivedClass(string word) : BaseClass(word) { cout<<word<<"  ==> Derived class constructor\n"; };
If we now declare an object of the DerivedClass initialized with the new constructor, then the new constructor of the derived class will explicitly call the alternative constructor of the BaseClass. For example, the line
DerivedClass obj("Alternative");
in the main function will generate the following output:
Alternative Base class constructor
Alternative Derived class constructor
You can fine the
complete source code of the example on the example page.

If the base class has constructors but no default constructor, then a derived class constructor must explicitly call some of the base class constructors. Please try to comment out the default constructor in the previous example and compile the program. You will end up having the following error message:

derived_constr.cpp(21) : error C2512: 'BaseClass' : no appropriate default constructor available
This is another reason to recommend always have a default constructor in a class. However, you won't get any error if the base class has no constructors at all.

The following summarizes the rules for invoking the constructors (see [1] for details):

As you can guess, if we have a class C indirectly derived from a class A through a class B and we declare an object of the C type, then the constructor of B will be implicitly invoked before the C constructor, and the A constructor will be implicitly invoked before the B constructor starts. In other words, the constructors will be invoked accordingly the inheritance hierarchy from the base class to the derived class.

Situations with the destructors is a little bit easier. First of all, the destructors are executed in the order opposite to the inheritance hierarchy; that is, from the derived class to the base class. In other words, if an object of a derived class gets destroyed, then first the destructor of the derived class (is there is any) will be invoked, and then the destructor of the base class will be automatically called (again, if there is any). For example, the following code

#include <iostream>
using namespace std;

class BaseClass {
  public:
    ~BaseClass() { cout<<"Base class destructor\n"; };
};

class DerivedClass : public BaseClass {
  public:
     ~DerivedClass() { cout<<"Derived class destructor\n"; };
};

void main()
{
   DerivedClass object;
}
will generate the output:
Derived class destructor
Base class destructor
Unlike constructors, a destructor never explicitly invokes another destructor.

References:

  1. Object-oriented programming in C++ by Richard Johnsonbaugh and Martin Kalin, chapter 4.
  2. Object-oriented programming in C++ by Nicolai M. Josuttis, chapter 5.
  3. C++ from the beginning by Jan Skansholm, chapter 9.