Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

How to call overridden child methods in a vector

I am trying to loop over multiple different child classes of a parent. Ideally I would like to save the child objects in a vector of smart pointers. The following outputs "Update idle" for every call to the method Update. I would like for the call to be the overridden variants of the method. What is the best way of solving this problem?

#include <iostream>
#include <memory>
#include <vector>

class Foo
{
public:
    virtual void Update(){
        std::cout << "Update idle" << std::endl;
    }; 
};

class Foo1 : public Foo
{
public:
    void Update() override
    {
        std::cout << "Update Foo1" << std::endl;
    }
};

class Foo2 : public Foo
{
    void Update() override
    {
        std::cout << Bar() << std::endl;
    }

    std::string Bar(){
        return "Update Foo2";
    }
};


int main() {
    std::vector<std::shared_ptr<Foo>> vec{
        std::make_shared<Foo>(Foo{}), 
        std::make_shared<Foo>(Foo1{}), 
        std::make_shared<Foo>(Foo2{})
    };

    for (auto &&ptr : vec)
    {
        ptr->Update();
    }
}   

>Solution :

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

std::make_shared<T>(args) creates an new instance of T, passing args to T‘s constructor, and then returns that instance in a std::shared_ptr<T>.

As such, your code is not dynamically creating any Foo1 or Foo2 object for the vector at all. It is creating 3 dynamic Foo objects, all of which are copy-constructed from temporary Foo, Foo1 and Foo2 objects.

In other words:

std::make_shared<Foo>(Foo{}) is equivalent to new Foo(Foo{})

std::make_shared<Foo>(Foo1{}) is equivalent to new Foo(Foo1{})

std::make_shared<Foo>(Foo2{}) is equivalent to new Foo(Foo2{})

You actually want the equivalent of new Foo, new Foo1 and new Foo2, so use this instead:

std::vector<std::shared_ptr<Foo>> vec{
    std::make_shared<Foo>(), 
    std::make_shared<Foo1>(), 
    std::make_shared<Foo2>()
};

Online Demo

Even though your std::vector holds std::shared_ptr<Foo> elements, but std::make_shared<Foo1>() will return a std::shared_ptr<Foo1>() and std::make_shared<Foo2>() will return a std::shared_ptr<Foo2>(), this is OK because std::shared_ptr<Foo1> and std::shared_ptr<Foo2> are convertible to std::shared_ptr<Foo> by virtue of the fact that Foo1 and Foo derive from Foo.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading