Dear all,
maybe this an off-topic issue, because it does not directly relate to
shared_ptr and is more related to life time of objects and their validity
during construction and destruction.
There were the following issues:
1) childs validity depends on availability of parent and vise versa
2) in ctor one can not use the shared_from_this()
3) in destructor of the child the parent shared_ptr was inaccesible
ad 1) the doc's are clear: you can not make a cycle in shared_ptrs between
parent -> child and child -> parent. Thus now we use a weak_ptr for child ->
parent, but actually the child can not exist without parent. So if one shares
a child through a shared_ptr, a hypothetical situation could exist that its
parent get destroyed, but a child lifes on (in an invalid state due to missing
parent) because a client has requested it.
ad 2) this is quite unhandy, since I thought it would be handy to let the
parent create the childs passing itself. I think this can only be solved by
two way construction.
This may well turn out to be a fundamental problem. Consider two classes A and
B which are associated with each other. Object of class A is valid when it is
valid itself and when its associated object of class B is valid. When A gets
changed it is temporalily invalid. It updates first B, but if B asks services
from A during that call, it asks an invalid object. Reversing the order may
help, but A may have to update itself again after it calls B. For two related
classes it can be overseen, but of course real life applications have 1000 or
more classes. Btw to some extend Bertrand Meyer's book touches this subject,
but he only mentions the problem within a class (with public and private
members).
ad 3) the destructor of the child needed the parent to call another class.
However the parent was inaccessible because it was destroyed itself. This is
of course also a fundamental problem because when an object gets destroyed not
all of its members may be valid (the parent object is in an invalid state), so
calling the parent at that time was questionable too. The real problem was
that it needed form the parent its parent which was still valid, solutions are
obvious (but ugly)
Sample code:
struct Child;
struct Parent;
struct Child
{
Child(boost::shared_ptr<Parent> ptrParent)
{
m_ptrParent = ptrParent;
}
~Child()
{
boost::shared_ptr<Parent> ptrParent = m_ptrParent.lock();
if (ptrParent)
{
//never come here
}
}
boost::weak_ptr<Parent> m_ptrParent;
};
struct Parent : public boost::enable_shared_from_this<Parent>
{
Parent()
{
//won't work:
//m_ptrChild.reset(new Child(shared_from_this()));
}
boost::shared_ptr<Child> m_ptrChild;
};
void TestParentChild()
{
boost::shared_ptr<Parent> ptrParent(new Parent);
ptrParent->m_ptrChild.reset(new Child(ptrParent));
}
wkr,
me