Boost logo

Boost Users :

From: Lang Stefan (SLang_at_[hidden])
Date: 2008-06-23 04:59:47


-----Ursprüngliche Nachricht-----

On Jun 20, 2008, at 8:38 AM, gast128 wrote:

> 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
>
> [snip]

1) If you have cyclic dependencies parent<->child (or other), the design is wrong (see below for a solution)
2) If you mean using a shared pointer from your parent class to hand to your child - you shouldn't be using shared_ptr in the first place. A shared_ptr implies you have the means and the right to destroy the object! A weak_ptr is all you need.
3) If a child needs sth the parent can supply, then make it accessible through another class (see below)

The basic solution to cyclic dependencies of classes is extracting parts of one class into another and have the original class (minus those parts) inherit from it. Here's a short example:

// original structure:
class B; // forward decl
class A {
public:
  ~A();
  void someService();
private:
  B* myChild;
};
A::A() : myChild(new B(this)) {
}
A::~A() {
  delete myChild;
}
class B {
public:
  B(A*);
  ~B();
private:
  A* myParent;
};
B::B(A* parent) : myParent(parent) {
}
B::~B() {
  myParent->someService(); // problem: if called during destruction, myParent may be invalid!
}

// suggested structure:
class B; // forward decl
class C {
public:
  void someService();
}
class A : public C {
public:
  ~A();
private:
  B* myChild;
};
A::A() : myChild(new B(this)) {
}
A::~A() {
  delete myChild;
}
class B {
public:
  B(C*);
  ~B();
private:
  C* myServiceProvider;
};
B::B(C* sp) : myServiceProvider(sp) {
}
B::~B() {
  myServiceProvider->someService(); // no problem!
}

Please note that even if A may be invalid during destruction, it's base class C is still valid as long as A's destructor isn't finished!

Hope this helps,
Stefan

P.S.: I didn't bother with shared pointers in my example, but since cyclic dependencies are an independent problem you can just choose to use shared pointers instead (or not).


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net