# Chapter 11 - Notes

## Inheritance Recap&#x20;

* Inheritance allows you to create class hierarchies
* Public inheritance models an 'is-a' relationship&#x20;

## Polymorphism&#x20;

Polymorphism is a feature of OOP languages that allows objects of different types to be treated similarly through inheritance. We will focus on *subtype polymorphism*.

## Polymorphic Behaviour&#x20;

The issue present is that if a user with an instance of a **derived class** uses a **variable of the base class type** to invoke an **overridden member method**, the **base class' method** is called.

```cpp
class Base {
    void foo() {
        std::cout << "I am Base" << std::endl;
    }
};

class Derived: public Base {
    void foo() {
        std::cout << "I am Derived" << std::endl;
    }
};

void invokeFoo(Base& x) {
    x.foo();
}

int main() {
    Derived derived;
    invokeFoo(derived);  // This prints "I am Base" 
}
```

Ideally the **overridden member method of the derived class** should be invoked despite accessed through a **variable of the base class type**.&#x20;

This can be achieved by declaring the function in the base class as a **virtual function** using the keyword `virtual`:

```cpp
class Base {
    virtual void foo() {
        std::cout << "I am Base" << std::endl;
    }
};

class Derived: public Base {
    void foo() {
        std::cout << "I am Derived" << std::endl;
    }
};

void invokeFoo(Base& x) {
    x.foo();
}

int main() {
    Derived derived;
    invokeFoo(derived);  // This now prints "I am Derived" 
}
```

{% hint style="info" %}
This is very important, as it implies that even without knowing the exact type of `Base` being handled, the call to `.foo()` in `invokeFoo` can result in different implementations of `.foo()` defined in any derived classes being invoked – all through a base class instance.&#x20;
{% endhint %}

### Virtual Destructors&#x20;

When the destructor of a base class is not defined as a virtual function (virtual destructor), calling the `delete` operator using a pointer of type `Base*` that actually points to an instance of type `Derived` would only call the destructor of the base class.&#x20;

Therefore, base class destructors should always be defined as `virtual`.

## Virtual Function Table&#x20;

At compile time, the compiler knows nothing about the nature of objects that the `invokeFoo` method will encounter to be able to ensure that the correct function ends up executing at each point in time. Therefore, the correct derived class implementation of to be invoked is a **decision made at runtime**.

Consider the following class `Base` that declares 3 virtual functions:&#x20;

```cpp
class Base {
public:
    virtual void One() {
        // ...
    }
    
    virtual void Two() {
        // ...
    }
    
    virtual void Three() {
        // ...
    }
};
```

And class `Derived` that overrides all functions from `Base` except `Base::Two()`:

```cpp
class Derived: public Base {
public:
    void One() {
        // ...
    }
    
    // Does not override Base::Two()
    
    void Three() {
        // ...
    }
};
```

The compiler creates a table called the Virtual Function Table (VFT) for **every class that implements a virtual function**, or a **derived class that overrides it**.&#x20;

In this example, both classes `Base` and `Derived` get an instance of their own VFT.&#x20;

The VFT for `Base` is shared between all instances of `Base`, and the VFT for `Derived` is shared between all instances of `Derived`. In other words, they're similar to a **static member variable**.&#x20;

The VFT can be imagined as a static array containing function pointers, each pointing to the virtual function or override of interest.&#x20;

![](https://4122513583-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MSrqC8yBLK9rXNyJ6ol%2F-M_FSFcv8ERKgIWVyLHS%2F-M_FSHXQYliaSvvYDX2Y%2Fimage.png?alt=media\&token=32c3abad-2387-424f-a746-86696c77c73a)

Each table is comprised of function pointers, each pointing to the available implementation of a virtual function. In the `Derived` class, functions `One()` and `Three()` point to local implementations, but `Two()` points to the implementation in `Base` since it has not overridden it.&#x20;

When a member function is called on a an instance that has a VFT, the compiler ensures a lookup in the VFT and ensures that the correct implementation is invoked.&#x20;

## Querying a Base Type Pointer

C++ allows you to query a base type pointer `Base*` if it is of type `Derived*` using the casting operator `dynamic_cast`, and performing conditional execution based on the result of the query.&#x20;

This is called runtime type identification (RTTI) and should be avoided if possible as it leads to poor programming practice.&#x20;

```cpp
#include <iostream>

struct Base {
    // Define a virtual function to make `Base` polymorphic
    virtual void hello() {};  
};

struct Foo: public Base {};

struct Bar: public Base {}; 

int main() {
    Base* x = new Foo;
    
    if (dynamic_cast<Foo*>(x)) {
        std::cout << "x is Foo" << std::endl;
    } else {
        std::cout << "x is not Foo" << std::endl;
    }

    if (dynamic_cast<Bar*>(x)) {
        std::cout << "x is Bar" << std::endl;
    } else {
        std::cout << "x is not Bar" << std::endl;
    }

    delete x;
}
```

## Abstract Base Classes (ABCs)

An **abstract base class (ABC)** is a base class that cannot be instantiated. Such a class serves only one purpose – that is to be derived from.&#x20;

In C++ there isn't an `abstract` keyword to declare an abstract base class unlike other languages such as Java:

```java
public abstract class AbstractJavaClass {}
```

Instead, an abstract class is defined by declaring a **pure virtual function**:

```cpp
class AbstractCppClass {
public:
    virtual void foo() = 0;  // Pure virtual function 
};
```

The declaration of a pure virtual function tells the compiler that the function needs to be implemented by any classes that derive from the abstract class (unless the derived class should also be an abstract class).

A class that that can be instantiated, that derived from an abstract base class is called a **concrete class**.&#x20;

{% hint style="info" %}
The reason `= 0` is used to define a pure virtual function is purely syntactic. It is not the case that 0 is being assigned to the function.&#x20;

The reason `= 0` is used is that [Bjarne Stroustrup](https://en.wikipedia.org/wiki/Bjarne_Stroustrup) didn't think he could get another keyword, such as "pure" past the C++ community at the time the feature was being implemented.
{% endhint %}

### Purpose of ABCs

Abstract base classes allows programmers to **enforce that all derived classes have to provide an implementation** for its pure virtual function(s).&#x20;

These functions can then be used as an "interface" of sorts.

```cpp
class Language {
public:
    virtual void greet() = 0;  // Pure virtual function 
};

class English {
public:
    void greet() { std::cout << "Hello" << std::endl }
};

class French {
public:
    void greet() { std::cout << "Bonjour" << std::endl }
};

class Spanish {
public:
    void greet() { std::cout << "Hola" << std::endl }
};
```

`Language` is an abstract base class. In this context it does not make sense for it to implement a `Language::greet` function (what would it return?)&#x20;

Therefore, we define it as a pure virtual function such that any concrete classes that derive from it have to implement it.&#x20;

{% hint style="info" %}
Although ABCs cannot be instantiated, you can still use variables, references, or pointers with the type of an ABC.&#x20;
{% endhint %}

## The Diamond Problem&#x20;

The diamond problem occurs when two base classes of a particular class share a common base class:

![](https://firebasestorage.googleapis.com/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MSrqC8yBLK9rXNyJ6ol%2Fuploads%2Fg34M74ziHy5s9lZjyeO0%2Ffile.png?alt=media)

In this example, class `D` inherits from `B` and `C`, who share a common base class `A`.

However, initialising `D` will call the constructor of `A` twice. And accessing/setting any member variable of `A` through `D` will result in a compilation error.

This is because the reality is closer to this:

![](https://firebasestorage.googleapis.com/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MSrqC8yBLK9rXNyJ6ol%2Fuploads%2FkhQ8e9nY9HbpQNiZlykU%2Ffile.png?alt=media)

Meaning it is ambiguous if setting `D::A::x` actually refers to `D::B::A::x` or `D::B::A::x`.&#x20;

In nearly all cases you'd expect the relationship to be: `D` is an `B`, is a `C`, and is also an `A`, and therefore it does not make sense for `D` to have **two** instances of `A`.&#x20;

The solution is **virtual inheritance**. If you expect a derived class to be used as a base class, it is a good idea to define its relationship using the keyword `virtual`:&#x20;

```cpp
struct ClassA {
    int x;
};

struct ClassB: public virtual ClassA {};

struct ClassC: public virtual ClassA {};

struct ClassD: public ClassB, public ClassC {};

int main() {
    ClassD obj;
    obj.x = 10;  // This is now ok! 
}
```

Because of the keyword `virtual` inheritance used by classes `ClassB` and `ClassC`, it is ensured that when these classes are inherited together under `ClassD` that the common base class `ClassA` exists only in a single instance.&#x20;

This solves the ambiguity problem described before.&#x20;

## Enforcing Intention to Override&#x20;

Consider the following base class with a virtual function:

```cpp
struct Base {
    virtual void foo() {
        std::cout << "I am Base" << std::endl;
    };
};
```

Now assume that a derived class were to define a function `foo()` but with a slightly different signature – one using `const` to denoting that it's a constant function:

```cpp
struct Derived {
    void foo() const {
        std::cout << "I am Derived" << std::endl;
    };
};
```

This function will **not** override `Base::foo()` as the signature is different due to the presence of `const`. However the program will continue to compile, but will likely result in behaviour different to that expected by the programmer.&#x20;

We can use the specifier `override` to express the intend to override a virtual method in  the base class.&#x20;

```cpp
struct Derived {
    void foo() const override {
        std::cout << "I am Derived" << std::endl;
    };
};
```

This will result in a compilation error as the compiler is unable to find a virtual function in the base class with the same signature.&#x20;

Thus, `override` provides us the ability to explicitly express the intention to override a base class function by getting the compiler to check whether:

* The base class function is `virtual`
* The signature of the base class matches the derived class function declared to `override`

The programmer can now fix this compilation error by either adding `const` to the virtual function in the base class, or removing `const` from the overriding function in the derived class.

## Prevent Function Overriding&#x20;

Recall that using the `final` specifier as part of a class definition ensures that the class cannot be derived from.&#x20;

Similarly a `virtual` function that's declared as `final` cannot be overridden in a derived class.&#x20;

```cpp
class Fish {
public:
    virtual void swim() = 0; 
}

class Tuna: public Fish {
public:
    // Override Fish::swim() and make it final 
    virtual swim() override final {
        std::cout << "Tuna swims!" << std::endl;
    }
};

class BluefinTuna final: public Tuna {
public:
    // Error: swim() was final in Tuna, cannot override
    virtual swim() { 
        // ...
    }
};

// Error: BluefinTuna is final cannot, cannot inherit
//   or use as a base class. 
class SmallBluefinTuna: public BluefinTuna {
};
```

## Virtual Copy Constructors?

Virtual copy constructors would be extremely useful, for example when creating a collection of type `Base*` whose elements are specialisations of `Base`, then assigning each element into another array of the same `Base*` type.&#x20;

The virtual copy constructor would ensure a deep copy of each specialised class, despite working with type `Base*`.&#x20;

Virtual copy constructors are however not possible because the `virtual` keyword is to do with polymorphic behaviour generated at runtime. Constructors are not polymorphic in nature as constructors can only construct a fixed type, and therefore not allowed in C++.&#x20;

### Workaround&#x20;

A trivial workaround for this would be defining a clone function which returns a pointer to a copy of the instance.&#x20;

```cpp
struct Number {
    // Pure virtual function
    virtual Number* clone() = 0; 
};

struct Integer: public Number {
    int* value;
    
    Integer(int number) {
        value = new int(number);
    }
    
    Number* clone() {
        // Create a new `Integer` with the same value
        return new Integer(*value);  
    }
};

struct Decimal: public Number {
    double* value;
    
    Decimal(double number) {
        value = new double(number);
    }
    
    Number* clone() {
        // Create a new `Bar` with the same value
        return new Decimal(*value);  
    }
};

int main() {
    Number* number = new Integer(3);  // or new Decimal(5.0);
    Number* number_copy = number->clone();
    
    delete number;
    delete number_copy; 
}
```
