Namespaces
Variants
Views
Actions

Inheritance in C++

From cppreference.com


The concept of inheritance in object-oriented languages is modeled in the fashion of inheritance within the biological tree of life. It is the mechanism by which incremental changes in a type or class are implemented. Inheritance establishes an is-a relationship between a parent and a child. The is-a relationship is typically stated as as a specialization relationship, i.e., child is-a parent.

In times where additional specificity is required, the is-a relationship can be further clarified as kind-of for inheritance of implementation and type-of for inheritance of interface.


For example, an ImaginaryNumber is-a Number.

Number
the parent, also called a superclass, parent class, base class, or in special cases
abstract base class.
ImaginaryNumber
the child, also called a subclass, subtype, or derived type/class.

[edit] Inheritance by Example

Inheritance in C++ is accomplished using the : operator. Continuing with the Number and ImaginaryNumber example used above, consider the following code sample.

class Number
{
public:
    Number()                         = default;
    Number( Number const& )          = default;
    virtual ~Number()                = default;
 
    virtual bool isImaginaryNumber() const noexcept = 0;
    virtual bool isRealNumber()      const noexcept = 0;
};
 
class ImaginaryNumber : public Number
{
public:
    ImaginaryNumber() 
    : m_realComponent( 0.0 ), m_imagComponent( 0.0 )
    {}
 
    ImaginaryNumber( ImaginaryNumber const& arg )
    : m_realComponent( arg.m_realComponent ),
      m_imagComponent( arg.m_imagComponent )
    {}
 
    virtual ~ImaginaryNumber() = default;
 
    virtual bool isImaginaryNumber() const noexcept { return true;  }
    virtual bool isRealNumber()      const noexcept { return false; } 
 
private:
    long double m_realComponent;
    long double m_imagComponent;
};


The inheritance of class Number by class ImaginaryNumber at the point of declaration for class ImaginaryNumber.

class ImaginaryNumber : public Number
{
// class member declarations/definitions.
};

In this example, class ImaginaryNumber declares that it is-a class Number and that the members of class Number should be visible according to their declaration in class Number. That is to say, all public members of class Number are visible to all modules within the codebase that includes both classes. Likewise the protected members of class Number are visible only to code within class ImaginaryNumber and private members of class Number are not visible to other modules in the program.


The example demonstrates what is perhaps the most common type of inheritance encountered within a C++ codebase. This type of inheritance is used to create a hierarchy of objects that represent a concept, in this example the concept of a Number, that is the base class for ImaginaryNumber. The 'inheritance to create a class hierarchy in C++' is what Cardelli and Wegner [1] refer to as universal inclusive polymorphism. With this type of inheritance, virtual or pure virtual methods are used to define points of extension for subclasses.


The declaration of virtual method conforms to the pattern:

virtual return-type methodName( methods-args ) method-characteristics ;


The declaration of a pure virtual method conforms to the the pattern:

virtual return-type methodName( methods-args ) method-characteristics = 0;


The base class, Number, provides the declaration of two pure virtual methods.


virtual bool isImaginaryNumber() const noexcept = 0;
A pure virtual method that is used to query if an instance of Number is an imaginary number.
virtual bool isRealNumber()      const noexcept = 0;
A pure virtual method that is used to query if an instance of Number is a real number.


The subclass ImaginaryNumber provides implementations of the two pure virtual methods declared in the superclass Number.


virtual bool isImaginaryNumber() const noexcept { return true;  }
The implementation appropriate to an ImaginaryNumber, always returns true.
virtual bool isRealNumber()      const noexcept { return false; }
The implementation appropriate to an ImaginaryNumber, always returns false.


Additional types of inheritance are described in the section on polymorphism.

[edit] References

[1] P. Wegner, L. Cardelli, “On Understanding Types, Data Abstraction, and Polymorphism,” 1985.

[2] Polymorphism