Demystifying Virtual and Abstract Functions
Tags: cpp, coding, oop, beginners
Published: 2018-03-02 19:26:21

---
title: Demystifying Virtual and Abstract Functions
published: true
description: Virtual inheritance looks like a strange beast at first glance, but rest assured, it's a friendly beast.
tags: cpp, coding, oop, beginner
cover_image: https://thepracticaldev.s3.amazonaws.com/i/dhgskg0zhb4ze2c7bnle.jpg
---

**EDIT:** After some superb comments, I've made some corrections to my original code: (1) `virtual` destructors, and (2) use of the `override` and `final` keywords.

---

Have you ever noticed C++'s inheritance system behaving in a way you didn't expect? Perhaps the base class's function kept getting called, and you didn't know how to have the derived class's function called instead. Or maybe you encountered some weird code in the class definition, things like `virtual` and `=0;`.

These all relate to **virtual inheritance**, which isn't nearly as scary as it first looks! Let's create a basic example to demonstrate what's going on with `virtual`, and why it is so awesome.

Let's imagine that we have a basic class, `Animal`, and that we derive a new class `Dog` from it...

```c++
class Animal
{
public:
    Animal(){}

    void eat()
    {
        std::cout << "Nom nom nom" << std::endl;
    }

    void sit()
    {
        std::cout << "[stares blankly]" << std::endl;
    }

    void speak()
    {
        std::cout << "[undefined sound]" << std::endl;
    }

    ~Animal(){}
};

class Dog : public Animal
{
public:
    Dog(){}

    void sit()
    {
        std::cout << "[sits]" << std::endl;
    }

    void speak()
    {
        std::cout << "woof" << std::endl;
    }

    ~Dog(){}
};

class Cat : public Animal
{
public:
    Cat(){}

    virtual void sit()
    {
        std::cout << "[meows disdainfully and walks away]" << std::endl;
    }

    virtual void speak()
    {
        std::cout << "mew" << std::endl;
    }

    ~Cat(){}
};

int main()
{
    Dog* dog = new Dog();
    Cat* cat = new Cat();

    dog->eat();
    dog->sit();
    dog->speak();

    cat->eat();
    cat->sit();
    cat->speak();
}
```

This class would define a basic animal, so we can reuse some functions, such as `eat()`, which are common to all animals.
Then we override `sit()` and `talk()` to be specific to `Dog`. It all works pretty well!

> Nom nom nom
> [sits]
> woof
> Nom nom nom
> [meows disdainfully and walks away]
> mew

Great! That does exactly what we want. However, one of the advantages of inheritance is that we can write functions like this...

```c++
void makeAct(Animal* critter)
{
    critter->eat();
    critter ->sit();
    critter->speak();
}
```

So, instead of writing two (or more) functions that do the same thing for each type of animal, we just accept the *base class* (or a pointer/reference to it) as the argument type. Then, we can do this...

```c++
int main()
{
    Dog* dog = new Dog();
    Cat* cat = new Cat();

    makeAct(dog);
    makeAct(cat);
}
```

**Here is where things get weird!** When we run this, we get...

> Nom nom nom
> [stares blankly]
> [undefined sound]
> Nom nom nom
> [stares blankly]
> [undefined sound]

Oy oy! That's not what we're looking for, is it? Where's our woofs and mews? Why isn't the dog sitting and the cat aloofing? They're all acting like the boring base `Animal` class!

This is where `virtual` functions come in handy. By default, the compiler looks to the base class for the function definition. **`virtual` tells the computer to look at the *derived* class for the function definition instead.**

Going hand-in-hand with this are **abstract** classes, a special type of `virtual` function that **must** be defined in the derived class. To break this down:

* `virtual` functions *may* be overridden by the derived class; the derived's version of the function will be used, even if the base class is used as the data type.

* *abstract* or *pure virtual* functions *MUST* be overridden by the derived class - they don't even have a definition in the base class.

`eat()` is pretty much the same among all animals, so that's fine as it is. However, we know that we should optionally override `sit()`; untrained animals *would* stare blankly, but some would respond in specific ways.

Looking at our class design, we also realize that `speak()` is a rather stupid function to define in `Animal`...printing "[undefined sound]" just looks dumb. Any animal we define should have a sound, or else explicitly say something like "[no sound]". So, we'll make this *pure virtual*.

**DESIGN PRINCIPLE:** Explicit is better than implicit. In other words, every situation should have some specifically designated action (or failure) in the code. This is also why we defined explicitly empty constructors and destructors in all our classes, instead of having the compiler implicitly define them.

So, let's rewrite so that `sit()` is `virtual`, and `speak()` is *pure virtual*.

Our base class should also have a virtual destructor.

```c++
class Animal
{
public:
    Animal(){}

    void eat()
    {
        std::cout << "Nom nom nom" << std::endl;
    }

    virtual void sit()
    {
        std::cout << "[stares blankly]" << std::endl;
    }

    virtual void speak() = 0;  // the `= 0;` literally means "not defined here"

    virtual ~Animal(){}
};
```

Meanwhile, in the derived classes, we add the `[override](http://en.cppreference.com/w/cpp/language/override)` keyword (C++11 and later) to each of the functions we are overriding. This gives us compiler errors if we are trying to override a non-virtual function.


```c++
class Dog : public Animal
{
public:
    Dog(){}

    void sit() override
    {
        std::cout << "[sits]" << std::endl;
    }

    void speak() override
    {
        std::cout << "woof" << std::endl;
    }

    ~Dog() override {}
};
```

We can also use the `[final](http://en.cppreference.com/w/cpp/language/final)` keyword (C++11 and later) instead of `override` if we don't plan to override that function later.

Dogs might make different sounds and behave differently, so we might derive from `Dog` and make classes for specific breeds. Cats, on the other hand, basically all say "mew", and none of 'em will sit for you, so there's no need to override those further! Thus, for the `Cat` class, instead of using `override`, let's just use `final`, to prevent further overriding!

```c++
class Cat : public Animal
{
public:
    Cat(){}

    void sit() final
    {
        std::cout << "[meows disdainfully and walks away]" << std::endl;
    }

    void speak() final
    {
        std::cout << "mew" << std::endl;
    }

    ~Cat() override {}
};
```

Later, if we try to override the `speak()` or `sit()` function in a class derived from `Cat`, we'll get a compiler error.

Now let's rerun that code from earlier. Here it is again, in case you forgot. We haven't changed *anything* here!

```c++
void makeAct(Animal* critter)
{
    critter->eat();
    critter ->sit();
    critter->speak();
}


int main()
{
    Dog* dog = new Dog();
    Cat* cat = new Cat();

    makeAct(dog);
    makeAct(cat);
}
```

When we run it, we see...

> Nom nom nom
> [sits]
> woof
> Nom nom nom
> [meows disdainfully and walks away]
> mew

Right on! Now everything works as we expect.

Now, one word of caution: if you define a function as *pure virtual* or *abstract* (i.e. `virtual thefunc() = 0;`, you MUST define it in each derived class. If you don't, you'll get a compiler error. Arguably, that's one of the benefits of pure virtual functions...the compiler is able to step in and keep you from doing stupid things.

That's it! `virtual` simply allows you to control where functions are called in a class inheritance. Not so scary now, is it?