Introduction

Polymorphism is a common coding concept that trips up many new developers; but what is it? Well, the exact definition of the word reads like so:

the condition of occurring in different forms.

So how does it apply to programming? In this post I’ll show how it applies with examples in C++.

Polymorphism Applications

Before getting to the examples in C++, let’s look at how polymorphism is practical in programming in general. The concept usually comes up in situations where you have many classes that are “related” to one another via inheritance.

Polymorphism allows you to use the base class of an inheritance tree to reference the implementation in a child class. What does that mean in practice? Let’s look at an example.

Examples

Dynamic Polymorphism

Let’s say we want to model in our code different “tools” that represent real world hardware (i.e. a hammer, screwdriver and so on). We might design our code in the following way:

polymorphism-example-uml

Now consider the following code that roughly implements the above diagram:

class Tool
{
    public:
        virtual void doWork()
        {
            std::cout << "Tool doing work" << std::endl;
        }
};

class Hammer : public Tool
{
    public:
        void doWork() override
        {
            std::cout << "Hammering" << std::endl;
        }
};

class Drill : public Tool
{
    public:
        void doWork() override
        {
            std::cout << "Drilling" << std::endl;
        }
};

int main()
{
    Hammer hammer;
    Drill drill;
    std::vector<Tool*> tools { &hammer, &drill};
    for(auto tool: tools)
    {
        tool->doWork();
    }
    return 0;
}

If you run the above code, the output is:

Hammering
Drilling

I encourage you to run this code yourself and play around with it before moving on.

If you consider what we did though, that's actually quite remarkable. The `Tool` class has a default implementation of the `doWork()` method, but we *override* the method in the child classes. This is polymorphism; specifically *dynamic* polymorphism. Basically this is allowing us to use a abstract interface (`Tool`) to access the `doWork()` member function of the child classes (`Hammer`, `Drill`). Even though the objects in our vector are `Tool` pointers, the function called is the appropriate implementation from the child object. This choice is thus happening at runtime, hence the label of *dynamic* polymorphism.

Static Polymorphism

How about static polymorphism? This means that the selection of the proper method or function is selected at compile time (not runtime). This selection doesn’t change unless the code changes. Consider the following example:

#include <iostream>
void demo(int index)
{
    std::cout << "Demo: " << index << std::endl;
}

void demo(int index, bool ok)
{
    if(ok)
    {
        std::cout << "Demo Ok: " << index << std::endl;
    }
}

void demo(int index, bool ok, double value)
{
    if(ok)
    {
        std::cout << "Demo Ok, Value: " << value << std::endl;
    }
}

int main()
{
    demo(3);
    demo(4, true);
    demo(5, true, 13.4);
    return 0;
}

The output of this code is:

Demo: 3
Demo Ok: 4
Demo Ok, Value: 13.4

Again I encourage you to try this out yourself. You can even challenge yourself to add another overload of the demo function with four inputs.

Here we see an example of static polymorphism. We have 3 functions called demo with different input parameters. The calls are resolved based on the input paramaters (i.e. they are resolved at compile time), hence why we call this static polymorphism.

Conclusion

I hope this brief look at polymorphism has given you a decent grasp of what it means in C++. Thanks for reading and happy coding! If you want to learn more about C++ be sure to follow this blog and checkout my YouTube channel.

Leave a Comment

Your email address will not be published. Required fields are marked *

Loading...