I'm trying to create a child class that can add itself to the parent's vector from its own constructor, but the problem is that i can't use enable_shared_from_this
and shared_from_this()
according to this :
It is permitted to call shared_from_this only on a previously shared object, i.e. on an object managed by std::shared_ptr (in particular, shared_from_this cannot be called during construction of *this).
class Parent
{
public:
Parent(){}
void addChild(const std::shared_ptr<Child>& child)
{
_childs.push_back(child);
}
private:
std::vector<std::shared_ptr<Child>> _childs;
};
class Child
{
public:
Child(const std::shared_ptr<Parent>& parent)
{
parent->addChild(...); // Here the problem
}
}
int main()
{
auto parent = std::make_shared<Parent>();
auto child = std::make_shared<Child>(parent);
return 0;
}
I've found this question but it does not answer my problem, I want to be able to add the child class to the parent class only from the constructor without having to go through another function after. Is it possible ?
CodePudding user response:
It's not possible I believe because make_shared
will first allocate the child and only after complete the shared_ptr
. Plus there is no way to get the address of the shared_ptr
in the child constructor.
I think what you have to do is change your addChild
method:
std::shared_ptr<Child> addChild() {
_childs.push_back(std::make_shared<Child>());
return _childs.back();
}
auto parent = std::make_shared<Parent>();
auto child = parent->addChild();
You can keep the void
if you want, this is just to keep more in line with your existing code.
PS: the plural of child is children.
CodePudding user response:
From cppreference:
struct Best : std::enable_shared_from_this<Best> // note: public inheritance
{
std::shared_ptr<Best> getptr() {
return shared_from_this();
}
// No public constructor, only a factory function,
// so there's no way to have getptr return nullptr.
[[nodiscard]] static std::shared_ptr<Best> create() {
// Not using std::make_shared<Best> because the c'tor is private.
return std::shared_ptr<Best>(new Best());
}
private:
Best() = default;
};
You just make the constructor private and use static method create
with arguments you need.
So after you inherit std::enable_shared_from_this<Child>
your main function will be:
auto parent = std::make_shared<Parent>();
auto child = Child::create(parent);
And you would be able to safely pass std::shared_ptr<Child>
to Parent
in constructor.