4

I have a parent object that has some other objects as fields. The parent object fully owns these fields: they can be declared as fields of the parent object (MyPart part), directly, not as references.

I would prefer to initialize these fields in constructor, but in some cases they do need to reach the parent object instance and call methods on it as they work. With raw pointers, I could simply pass this to they constructors or setters. I have just discovered however that creating smart pointer from this is something near impossible, because such pointer would not know when the parent object goes out of scope (for sure not where the constructor returns!). But I do known that being the fields of the parent object, these children definitely cannot outlive it.

The only "clean" idea I can so far imagine is to construct the object in some factory method where reference to the constructed parent can be a smart pointner, then construct children separately and use the setter to compose the parent. Is this really the best approach?

As we have now policy to avoid raw pointers at all costs, what other options could I have? Or just using raw pointers in such a case is appropriate?

  • 2
    Use a reference Parent&, and pass it *this if you truly need access to the parent. If the child needs access to the parent through a std::shared_ptr<>, you can have the parent inherit std::enable_shared_from_this see here. This will allow a shared_ptr to be constructed by this->shared_from_this(). Unless you are implementing a data structure this is almost certainly poorly designed. Whatever child needs of Parent try and extract it into a common class, this way it can be fully constructed before use. – Kain0_0 Mar 22 at 6:00
  • 1
    Raw pointers shouldn’t own data (because you could forget to delete them), but it’s fine to use them to reference data or to access data. – J. Antonio Perez Mar 22 at 7:42
7

You can use a reference to the parent. As a sketch

class Parent;

class Child {
private: 
    Parent & parent;
public:
    Child(Parent & p) : parent(p) {}
    // other members
};

class Parent
private:
    Child child;
public:
    Parent() : child(*this) {}
    // other members
};

As a bonus, the compiler will refuse to let you construct a Child without a Parent. You can go further, and make Child only privately constructable, and friend Parent.

  • The problem with using a reference is that Child is not assignable anymore. Using a pointer member variable avoids that. – D Drmmr Mar 23 at 20:02
  • @DDrmmr? it's a subobject of Parent, it doesn't need to be assignable – Caleth Mar 23 at 20:44
9

Just use a raw pointer, it is a non-owning pointer that has no implication on life-cycle.

And the child holding a parent pointer will not outlive the parent as you say they are non-pointer/reference members so parent will clean them up.

  • 1
    You may want to note that the pointer can't outlive the parent, because it is (transitively) a subobject of the parent. – Caleth Mar 21 at 12:11
5

Try to avoid coupling the field classes to the parent class. Any data that is in the parent, but is needed by the field, can be passed when calling a function of the field. Any function of the parent that needs to be called by a function of the field can be passed as a callback function (e.g. using std::function).

A mutual dependency between classes is often an indication that the code is ill structured. The flow of the program can quickly become unwieldy, making the code hard to maintain.

If the field really needs a reference to the parent, you can safely pass the this pointer to the field's constructor (even in the parent's initializer list), provided the field's constructor doesn't access the passed pointer, but only stores it.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.