Consider the following parent/child object model. The intention is for both the parent and the child to use shared_ptr to manage their lifetimes. The parent should keep a shared_ptr to (retain) its children, and the children will keep a weak_ptr to the parent.
Given that the intention is for these objects to always be managed by std::shared_ptr what is the best way to construct them? The method I've come up with (so far) feels a little clunky: I'm using factory (friend) functions and a private constructor to reduce the likelihood that raw pointers to these objects "escape". Then, the child creates a shared_ptr with this in the ctor, and puts that into the parent's vector of children. When the ctor returns the raw pointer to the factory function, the factory function uses shared_from_this() to get a shared_ptr that is "hooked up to" (i.e. sharing a reference count with) the shared_ptr that's in the parent's vector of children.
Here's what I've come up with so far:
class Child; // Forward decl class Parent : std::enable_shared_from_this<Parent> { public: int value() const { return _value; }; void set_value(int newValue) { _value = newValue; }; std::vector<std::shared_ptr<const Child>> children() const { // propagate const-ness to the child pointers we hand back. return std::vector<std::shared_ptr<const Child>>(begin(_children), end(_children)); }; std::vector<std::shared_ptr<Child>> children() { return _children; }; private: Parent(int value) : _value(value) {}; friend class Child; // So it can add itself to the _children vector friend class std::shared_ptr<Parent>; // So that I don't have to inherit public from enable_shared_from_this friend std::shared_ptr<Parent> CreateParent(int value); // So it can call the private ctor std::vector<std::shared_ptr<Child>> _children; int _value; }; class Child : std::enable_shared_from_this<Child> { public: int value() const { return _value; }; void set_value(int newValue) { _value = newValue; }; private: Child(const std::shared_ptr<Parent>& parent, int value) : _parent(parent), _value(value) { std::shared_ptr<Child> sp(this); // This feels wrong, but the existence of the shared_ptr in the parent's vector of children ensures that the precondition for calling shared_from_this() is met parent->_children.push_back(sp); }; friend std::shared_ptr<Child> CreateChild(const std::shared_ptr<Parent>& parent, int value); // So it cal call the private ctor friend class std::shared_ptr<Child>; // So that I don't have to inherit public from enable_shared_from_this std::weak_ptr<Parent> _parent; int _value; }; std::shared_ptr<Parent> CreateParent(int value) { return std::shared_ptr<Parent>(new Parent(value)); }; std::shared_ptr<Child> CreateChild(const std::shared_ptr<Parent>& parent, int value) { std::shared_ptr<Child> rv = (new Child(parent, value))->shared_from_this(); return rv; }; This seems to work, but man, does it feel clunky. Is there a better way?
CreateChildmethod.