Home > database >  Add a Child to its Parent from the constructor
Add a Child to its Parent from the constructor

Time:05-16

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.

  • Related