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 :
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>()
};
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.