Parent-Child Object Relationships with shared_ptr

Hello, I've been thinking of switching one of my projects to use boost::smart_ptr and I'm currently investigating this option a bit. In my project there are a lot of cases where an object acts as factory/parent object to create other child objects. These child objects must keep the parent object alive as long as one of them still exists. Or in other words, even if the client does not hold a pointer to the parent object anymore, the parent must continue to exist as long as there is still a child object. Also the child objects sometimes need to have access to the parent object that created them. Therefore, I thought I'd have them hold a shared_ptr to the parent object. So the situation looks something like this, where both Parent and Child objects are only allocated on the heap and should only be passed around as shared_ptr. class Parent { public: boost::shared_ptr<Child> CreateChild() const { boost::shared_ptr<Child> child(new Child(this)); return child; } }; class Child { friend class Parent; protected: Child(const boost::shared_ptr<Parent> parent) : m_parent(parent) {} private: boost::shared_ptr<Parent> m_parent; }; As far as I understand it I can't do new Child(this) because Child expects a shared_ptr, so I'd have to derive Parent from enable_shared_from_this. However, in my project there are a number of classes in a rather complicated class hierarchy to which the above pattern applies and I'd thus like to avoid having to (multiply) derive them from enable_shared_from_this. Is there another, possibly better way of achieving what I want to do (keep the parent alive as long as there are still child objects) that I haven't discovered yet? Or do I really have to derive all these classes from enable_shared_from_this? Do I have to derive each class in a class hierarchy from enable_shared_from_this, if each of them needs to give out a shared_ptr-managed this pointer? Thanks for any help, Martin

If I understand you problem right it comes down to not being able to pass a shared_ptr to "this"? If so, I had a similar problem in another project. My solution was for the "parent" class to have a member: boost::weak_ptr<parent> weak_this_ and a static named constructor. I have found that named constructors are one of your best friends in C++, they solve all those problems of "what can I do in the constructor?". The named constructor is called parent::create, and looks something like this: shared_ptr<parent> parent::create() { share_ptr<parent> new_parent = shared_ptr<parent>(new parent()); new_parent->set_weak_this(new_parent); return new_parent; } The shared_ptr new_parent is automatically converted to a weak_ptr when assigned with "set_weak_this" (you must store it as a weak_ptr or you will have double deletion problems - ie segfaults). Now to your problem, when you need to create a child using a smart_ptr to a parent "this", do it like this: // not sure if this can be const anymore... boost::shared_ptr<Child> CreateChild() { boost::shared_ptr<Child> child(new Child(weak_this_.lock())); return child; } That's it, you now have the ability to pass a shared_ptr to this by storing a weak_ptr to this and locking it as needed, and the user code will look something like: parent::ptr my_parent = parent::create(); child::ptr my_child = my_parent->CreateChild(); note: typedef boost::shared_ptr<parent> ptr; goes in the public section of the parent class header file. Darren Hart dvhart@byu.edu On Fri, 2003-08-22 at 10:57, Martin Ecker wrote:
Hello,
I've been thinking of switching one of my projects to use boost::smart_ptr and I'm currently investigating this option a bit.
In my project there are a lot of cases where an object acts as factory/parent object to create other child objects. These child objects must keep the parent object alive as long as one of them still exists. Or in other words, even if the client does not hold a pointer to the parent object anymore, the parent must continue to exist as long as there is still a child object. Also the child objects sometimes need to have access to the parent object that created them. Therefore, I thought I'd have them hold a shared_ptr to the parent object.
So the situation looks something like this, where both Parent and Child objects are only allocated on the heap and should only be passed around as shared_ptr.
class Parent { public: boost::shared_ptr<Child> CreateChild() const { boost::shared_ptr<Child> child(new Child(this)); return child; } };
class Child { friend class Parent;
protected: Child(const boost::shared_ptr<Parent> parent) : m_parent(parent) {}
private: boost::shared_ptr<Parent> m_parent; };
As far as I understand it I can't do new Child(this) because Child expects a shared_ptr, so I'd have to derive Parent from enable_shared_from_this. However, in my project there are a number of classes in a rather complicated class hierarchy to which the above pattern applies and I'd thus like to avoid having to (multiply) derive them from enable_shared_from_this. Is there another, possibly better way of achieving what I want to do (keep the parent alive as long as there are still child objects) that I haven't discovered yet? Or do I really have to derive all these classes from enable_shared_from_this? Do I have to derive each class in a class hierarchy from enable_shared_from_this, if each of them needs to give out a shared_ptr-managed this pointer?
Thanks for any help, Martin
Info: http://www.boost.org Wiki: http://www.crystalclearsoftware.com/cgi-bin/boost_wiki/wiki.pl Unsubscribe: mailto:boost-users-unsubscribe@yahoogroups.com
Your use of Yahoo! Groups is subject to http://docs.yahoo.com/info/terms/

Martin Ecker wrote: [...]
So the situation looks something like this, where both Parent and Child objects are only allocated on the heap and should only be passed around as shared_ptr.
class Parent { public: boost::shared_ptr<Child> CreateChild() const { boost::shared_ptr<Child> child(new Child(this)); return child; } };
The most straightforward way is to make CreateChild a free function (or a static member of Parent, or a static member of Child, depending on the design): shared_ptr<Child> CreateChild(shared_ptr<Parent> const & px) { shared_ptr<Child> child(new Child(px)); return child; } as described in http://www.boost.org/libs/smart_ptr/sp_techniques.html#from_raw If you need CreateChild to be virtual, enable_shared_from_this is the only option.
participants (3)
-
Darren Vincent Hart
-
Martin Ecker
-
Peter Dimov