# C++ Inheritance

## Summary


Inheritance is one of the most important principles of object-oriented programming. In C++, inheritance takes place between classes wherein one class acquires or inherits properties of another class. The newly defined class is known as **derived class** and the class from which it inherits is called the **base class**. Class inheritance reflects heredity in the natural world, where characteristics are transferred from parents to their children.

In C++, there are many types of inheritance namely, single, multiple, multilevel, hierarchical, and hybrid. C++ also supports different modes of inheritance. These are public, private, and protected.

Inheritance promotes *code reuse*. Reusing code not only makes code easy to understand but also reduces redundancy. Code maintenance is easier. Code reliability is improved.

## Discussion

### Could you explain C++ inheritance with an example?

Consider two different classes, `Dog` and `Cat`. Both classes might have similar attributes such as breed and colour. In C++, such attributes are called **data members**. The classes might also have similar behaviours or actions such as eat, sleep and speak. In C++, such actions are implemented as **member functions**. Instead of writing similar code in two different classes we can create an `Animal` class that brings together common attributes and behaviours. Classes `Dog` and `Cat` can inherit from `Animal` class. They can add their own functionalities.

In this example, `Animal` is the base class, `Dog` and `Cat` are derived classes. We may say that (Animal, Dog) represents a parent-child relationship. Dogs are inheriting characteristics of animals. We may also say that `Animal` is a generalization of `Dog` and `Cat`; and `Dog` and `Cat` are specializations of `Animal`. 

Derived classes can specialize by adding extra data members and member functions. They can also **override** the general behaviour defined in the base class. 

Inheritance in C++ follows a *bottom up* approach. Derived classes acquire properties from base classes but the reverse is not true.


### What are different types of inheritance in C++?

C++ supports many types of inheritance based on the number of base or derived classes and the class hierarchy:  

    + **Single Inheritance**: A derived class inherits from only one base class. Eg. `class B` inherits from `class A`.
    + **Multiple Inheritance**: A derived class inherits from more than one base class. Eg. `class C` inherits from both `class A` and `class B`.
    + **Multilevel Inheritance**: The class hierarchy is deeper that one level. Eg. `class C` inherits from `class B` that itself is inherited from `class A`.
    + **Multipath Inheritance**: A derived class inherits from another derived class and also directly from the base class of the latter. Eg. `class C` inherits from `class B` and `class A` when `class B` itself is inherited from `class A`.While the above types are about a single class, there are others that are about the structure of the class hierarchy. These are more design patterns than types:  

    + **Hierarchical Inheritance**: A base class is specialized in many derived classes, which in turn are specialized into more derived classes.
    + **Hybrid Inheritance**: This combines both multiple and hierarchical inheritance.

### How does C++ deal with the diamond problem or ambiguity?

The **diamond ambiguity** can occur with multiple inheritance. It happens when the base classes themselves are derived from another common base class. The final derived class ends up with multiple copies of the distant base class. 

Consider D inheriting from classes B1 and B2, B1 inheriting from A, and B2 inheriting from A. Thus, D has multiple copies of A. The problem occurs when a call is made to a member of A from an instance of D. C++ compiler can't determine which copy of A to use. Compilation will fail.

To solve this problem, C++ uses the concept of **virtual inheritance**. When inheriting A, B1 and B2 will specify the `virtual` keyword. The compiler sees this and creates a single instance or copy of A within D. No `virtual` keyword is needed when defining D.  

Having multiple copies of a base class is not really an error. In fact, it's possible to define a class that uses both virtual and non-virtual inheritance. Ultimately, the compiler should be able to determine member access *unambiguously*. 


### What's the concept of name hiding in C++?

**Name hiding** happens when a derived class has a member with the same name as a member of the base class. The derived class definition hides the base class definition. Thus, `Animal::age` is hidden by `Dog::age`. 

The concept is also related to but different from **overriding**. For example, `Dog::speak()` if defined overrides `Animal::speak()`. In addition, `Dog::speak()` can explicitly call the base class implementation with the statement `Animal::speak()`. 

C++ also allows functions to be **overloaded**, which is about having multiple member functions of the same name that differ in their parameter types. So, we could have `Animal::speak()` and the `Dog` class that defines only `Dog::speak(const string&)`. Unfortunately, in this case, `Dog` class doesn't have access to `Animal::speak()`. In this case, we have name hiding, not overriding. 

It's possible for `Dog` class to have access to `Animal::speak()` by simply including the line `using Animal::speak;` in its class definition. With this `using` directive, all the overloaded `speak()` functions of the base class become accessible in the derived class. 


### What is object slicing in C++?

When a derived class object is typecast into one of its base classes, we're doing what's called **object slicing**. Conceptually, it's similar to typecasting a decimal number to an integer type, whereby the number loses it's decimal portion. With object slicing, the object loses members specialized in the derived class and retains only those parts of the base class to which it's been typecast. 

Consider a base class A and a derived class B. Consider object b of type B. Object slicing happens with the assignments `A a = b` and `A& a_ref = b`. Assignment operator is not virtual in C++. Hence, in these assignments the assignment operator of A is called and not that of B. 

The figure shows another example. Base class defines data member `a` and virtual functions `bar1()` and `bar2()`. Derived class overrides `bar1()`, and adds `bar3()`, `bar4()` and `b`. An A-type slice of B can access `a`, derived class function `bar1()` and base class function `bar2()`. 


### What are compile-time and runtime bindings in the context of inheritance?

If the C++ compiler can determine what function to call at compile time, we call it **compile-time binding**, early binding or static dispatch. However, where virtual functions are defined in a base class and overridden by derived classes, the compiler can't know which function to call. This information is available only at runtime, giving rise to the terms **runtime binding**, late binding or dynamic dispatch.   

Suppose classes `Square` and `Triangle` are derived from `Shape`. Consider member functions `virtual void Shape::area() {...}`, `void Square::area() {...}` and `void Triangle::area() {...}`. Also defined is the function `paintArea(Shape& shape) { int area = shape.area(); ... }`. Exactly which area function is called inside `paintArea()`? This is known only at runtime. 

Under the hood, runtime binding relies on *vpointers* and *vtables*. Every class with virtual functions has a *vtable* that stores pointers to virtual function definitions. When a virtual function is overridden, the pointer would point to the derived class implementation. Every class with a *vtable* also has a *vpointer* that points to the correct *vtable*. 


### What are the rules of inheritance involving C++ abstract classes?

An abstract class in C++ has at least one pure virtual function, which essentially defines the interface but doesn't supply an implementation. Abstract classes are meant to be used as base classes for other class definitions. Abstract classes themselves can't be instantiated. Their very purpose is inheritance that conforms to an interface.

An abstract class can't be used as a parameter type, a function return type or the result of an explicit conversion. Pointers and references to an abstract class are allowed. 

If a derived class inherits from an abstract class without supplying implementations, the derived class is also an abstract class. Thus, "abstraction" can be inherited. On the other hand, it's possible to inherit from a non-abstract base class, add pure virtual functions or override a non-pure virtual function with a pure virtual function, and thereby define an abstract derived class. 

When a pure virtual function is called from a constructor, the behaviour is undefined. 


### What are the different visibility modes in inheritance in C++?

C++ supports three access specifiers: public, protected and private. These access specifiers are used on data members and member functions. If not explicitly mentioned, private access is the default.  

Likewise, a derived class can use an access specifier on each of its base classes. Available access specifiers are public, protected, and private. Where multiple inheritance is used, each base class can have a different access specifier. If not explicitly mentioned, private inheritance is the default. 

Regardless of the access specifier on the base class, base class private members will remain private; that is, derived class can't access them. For public and protected members of base class, we summarize how access specifier on the base class affects access to members of the derived class:  

    + **Public**: Public and protected members of base class become public and protected members of derived class respectively.
    + **Protected**: Public and protected members of base class become protected members of derived class.
    + **Private**: Public and protected members of base class become private members of derived class.

### What's the influence of access specifiers on virtual functions?

The figure shows three examples involving the member function `A::name()`. In (a), the function is non-virtual. Hence, when it's called via the base class pointer, `A::name()` is called. This is really compile-time binding.

In (b), the function is made virtual. Now when the same call is made, runtime binding happens and `B::name()` is called. Although `B::name()` is private, it's called via the base class pointer and `A::name()` itself is public. 

In (c), we make the inheritance protected. This makes `A::name()` protected in the derived class. This means that it can't be called from outside the class, such as from `main()`. Hence we get a compile-time error just as if `B::name()` had been declared protected or private. 


### How is inheritance of struct different from that of class?

Data structure `struct` comes from C programming language and is applicable in C++ as well. C++ extends `struct` so that it can include member functions. Like `class`, a `struct` definition can also be inherited. 

The main difference is that when access specifiers aren't specified, `struct` members are public by default whereas `class` members are private by default.  Likewise, when access specifiers are omitted in inheritance, `struct` inheritance is public by default whereas `class` inheritance is private by default. 

For completeness, we note that there's also `union` that comes from C. It's members are public by default. Unions can't be used as base classes. 


### What are the workings of C++ class constructors and destructors?

Constructors and destructors were traditionally not inherited. Since C++11, constructors could be inherited.  

Base class constructors are called before derived class constructors. In the case of multiple inheritance, base classes constructors are called in the depth-first left-to-right order of inheritance in the derived class. Destructors execute in reverse order.

Constructors have be defined as public or protected so that derived class constructors can call base class constructors. 

Constructors need not be virtual: constructors are always called by name. Destructors have to be virtual. In other words, it's not sufficient to destroy only the base class object. We need to destroy the original derived class object. 


### What are the main criticisms of C++ inheritance?

Inheritance in C++ is complex. Even a single inheritance has six variants: private/protected/public and virtual/non-virtual. With multiple inheritance, this complexity increases. The utility of a private virtual function is rather limited. 

The designer of a base class decides if a member function must be declared virtual. Derived class can't control this or prevent calls to base class non-virtual functions. Virtual inheritance is also a problem since the decision is made early. It prevents defining a derived class that wants two copies of the distant base class. 

C++ implementation of polymorphism via virtual functions can impact performance. Virtual member functions are not directly called. Instead, they've to be looked up via *vpointer* and *vtable*. 

## Milestones

Apr  
1979

At Bell Laboratories, inspired by Simula, Bjarne Stroustrup conceives the idea of *C with Classes*. The new language would combine the low-level features of C and high-level code organization of Simula. Even in these early days, the language includes classes, class hierarchies and **simple inheritance**. Also included are **private and public inheritance** of a base class. 

1983

To support runtime polymorphism, **virtual functions** are added to the language. Only with the introduction of virtual functions, the language claims to support **object-oriented programming**. This is also when the first implementation becomes available to users. Subsequently, the language is renamed to *C++* (1984) and the first commercial release happens (1985). 

Jun  
1989

C++ 2.0 is released. This includes support for **multiple inheritance** and **abstract class**. Abstract classes provide a "cleaner separation between a user and an implementor" and reduces compile times. 

Sep  
2011

ISO publishes the C++11 standard, formally named ISO/IEC 14882:2011. This release introduces identifiers `override` and `final`. These help manage complex class hierarchies. They can be applied on virtual member functions when overridden in a derived class. Identifier `final` can also be applied to a class so that it can't be inherited. **Constructors can now be inherited** with the `using` declaration.  This is useful when a derived object needs to be initialized in the same way as the base object. 

Dec  
2017

ISO publishes the C++17 standard, formally named ISO/IEC 14882:2017. It's now possible to do **aggregate initialization involving derived and base classes**.