Static vs Dynamic Polymorphism

I just learned static polymorphism and was spending my time learning what it is about for last few days.

We create dynamic polymorphism this way
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
class Animal
{
public:
    Animal(){}
    ~Animal(){}

    virtual void talk() = 0;    // Just talks
};

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

    void talk() override
    {
        std::cout << "Meow!" << std::endl;
    }
};

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

    void talk() override
    {
        std::cout << "Voof!" << std::endl;
    }
};

and use it
1
2
3
4
5
6
7
8
9
    std::vector<std::unique_ptr<Animal>> animals;

    animals.push_back(std::unique_ptr<Cat>(new Cat()));
    animals.push_back(std::unique_ptr<Dog>(new Dog()));

    for(std::unique_ptr<Animal> &animal : animals)
    {
        animal->talk();
    }


Now with static polymorphism
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
template<typename T>
class Animal
{
public:
    void talk()
    {
        static_cast<T*>(this)->talkImpl();
    }
};

class Cat : public Animal<Cat>
{
    friend class Animal;
private:
    void talkImpl()
    {
        std::cout << "Meow!" << std::endl;
    }
};

class Dog : public Animal<Dog>
{
    friend class Animal;
private:
    void talkImpl()
    {
        std::cout << "Voof!" << std::endl;
    }
};

and while using it
1
2
3
4
5
6
7
8
9
    std::vector<std::unique_ptr<Animal<WHAT_HERE>>> animals;

    animals.push_back(std::unique_ptr<Cat>(new Cat()));
    animals.push_back(std::unique_ptr<Dog>(new Dog()));

    for(std::unique_ptr<Animal<WHAT_HERE>> &animal : animals)
    {
        animal->talk();
    }


So coming to the question. While using static polymorphism are we giving up the ability to control every derived class without knowing what class they are? Or is there a way to this?
Last edited on
Unless I'm missing something, your "WHAT HERE" comments are a problem. You no longer have a common base class. Because Animal is a template class, Cat derives from Animal<Cat> and Dog derives from Animal<Dog>. There is no such thing as an Animal, so you cannot have common pointers to a base class.
What you have is called CRTP, Curiously Recurring Template Pattern, where a class inherits from a template and passes itself as a template parameter.
Yeah, and thats the reason, we give up(dont have) the ability of controlling derived classes while using static polymorphism right?

As a second question, do we have a workaround for this? To have that ability.

EDIT: Are there maybe other methods to create static polymorphism other than crtp?
Last edited on
What's the motivation of static polymorphism in C++
http://stackoverflow.com/a/19062918
@Duoas, i think, only after writing an example of static polymorphism i realized that such a thing was not possible. Which shocked me. It is that ability which amazes me about dynamic polymorphism. Thank you for the link by the way.

So i realized that it actually is a trade off. You choose which one better suits your needs.

Thanks for answering everyone.
You can have your template class inherit from a non-template base class, and thus have a common base class.
You can have your template class inherit from a non-template base class, and thus have a common base class.
Which comes back to using a mixture of static and dynamic polymorphism and therefore has no advantages over normal dynamic polymorphism, correct?
Even if we do so, cant use it for that purpose. For example:
1
2
3
4
5
6
7
8
9
10
    std::vector<std::unique_ptr<NonTemplateBase>> animals;

    animals.push_back(std::unique_ptr<Cat>(new Cat()));
    animals.push_back(std::unique_ptr<Dog>(new Dog()));

    for(std::unique_ptr<NonTemplateBase> &animal : animals)
    {
        animal->talk();    // error: It is no longer Animal class so no talk() function
                           // Casting it is also impossible
    }
Last edited on
Even if we do so, cant use it for that purpose. For example:

sure, just put a pure virtual method named talk in the non-template-base class.
Still, as mentioned before this involves dynamic polymorphism so you don't get any advantages.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
// Example program
#include <iostream>
#include <string>
#include <vector>
#include <memory>

class AnimalBase {
public:
    virtual void talk() const = 0;
};
template <typename T>
class Animal : public AnimalBase {
public:
    void talk() const final override { static_cast<const T*>(this)->talk_impl(); }
};

class Cat : public Animal<Cat> {
public:
    void talk_impl() const
    {
        std::cout << "Meow!" << std::endl;
    }
};

class Dog : public Animal<Dog> {
public:
    void talk_impl() const
    {
        std::cout << "Voof!" << std::endl;
    }
};

int main()
{
    std::vector<std::unique_ptr<AnimalBase> > va;
    va.push_back(std::make_unique<Dog>());
    va.push_back(std::make_unique<Cat>());
    va.push_back(std::make_unique<Dog>());
    
    for(const auto& a : va)
        a->talk();
}
Last edited on
@Gamer2015 Exactly :)
Last edited on
Still, as mentioned before this involves dynamic polymorphism so you don't get any advantages.

Wrong. You may not get the advantages of static polymorphism, but you do get the advantages of dynamic polymorphism.

The undertone of this thread, explicit or not, intended or not, is that static polymorphism is better than dynamic polymorphism. That's like saying a screwdriver is better than a hammer. You can use a screwdriver to drive a nail, but a hammer is much more suited to the job. There are many times when dynamic polymorphism is exactly what is needed, and trying to use static polymorphism just won't get the job done.
Guys calm down.

I am not saying one is better. I said
i realized that it actually is a trade off. You choose which one better suits your needs.


So i am on the side, whichever better fits your needs, use it.
Wrong. You may not get the advantages of static polymorphism, but you do get the advantages of dynamic polymorphism.
I meant to say "so you don't get any advantages by using static polymorphism in this case" but I don't know what else I could've wanted to say that you needed to "correct" me

still, i think this thread is done, I hope we could help you Ceset :)
Last edited on
Yes it is done and i appreciate every help
Topic archived. No new replies allowed.