Implementing Parent-Child and Similar Relationships

I have been thinking a lot lately about relationships between objects. These relationships come in three varieties:

  1. One object acts as the “creator” and “destroyer” for other objects. In this case,  the “creator/destroyer” object does not need to keep track of the objects that it created, but the created objects must keep a reference to the “creator/destroyer” so that the objects can destroy themselves. The program must destroy the created objects before destroying the “creator/destroyer” object. One object, the parent, owns the other objects, the children, and must destroy its children objects before destroying itself.One example of this would be in an object-oriented implementation of the Vulkan API. Once a logical device object has been created, it can be used to create and destroy any number of other objects such as swap chains, render passes, pipelines, frame buffers, command pools, semaphores, and so forth. The logical device should not be destroyed until all of the created objects are destroyed. Otherwise, GPU memory leaks occur.
  2. In a parent-child relationship, the children may be created before or after the parent. Child objects may be added or removed from the parent as required. The parent must maintain a reference to each of the children it owns, and each child must maintain a reference to its parent. The program must destroy each non-owned object. One place that a parent-child relationship could be implemented is in Tasks and Task Lists. The Task List would be the parent, holding a number of Task children. Again, the Task List must not be destroyed until all of the Tasks that it “owns” are destroyed.
  3. An extension of the parent-child relationship is where each child could in turn be the parent of other child objects.This sort of relationship shows up in graphical user interface libraries. For example, a main window contains a number of child widgets, each of which may contain zero or more other widgets, which in turn may contain…

The creator- destroyer pattern can be thought of as a specialized case of the parent – child relationship with the parent (the creator – destroyer object) not keeping track of the children objects. This pattern will not be discussed further.

The next several posts will look at three ways of implementing parent – child relationships, and a single way of implementing the multiple level parent-child relationship.

Generalized Parent – Child Relationship

To begin, let’s look at the parent – child relationship:

class Parent {
public:
    Parent(/* args as needed */);
    ~Parent();
    void addChild(RefToChild1 child);
    RefToChild2 findChild(RefToChild1 child);
    RefToChild2 removeChild(RefToChild1 child);
...
private:
    vector m_children;
};

class Child {
public:
    Child(RefToParent parent, /* other args as needed */);
    RefToParent getParent();
    const ID getID();
...
private:
    RefToParent m_parent;
    ID m_id;
};

The next thtee posts will look at Parent and Child classes where RefToChild1, RefToChild2, and RefToParent are raw pointers, shared_ptrs and weak_ptrs, and finally, a combination of raw pointers, shared_ptrs and unique_ptrs. The pros and cons of each approach will be discussed.

Multi-Level Parent – Child Relationships

Following the Parent – Child posts, we will look at the pattern where each class contains a link to a parent object and links to any child objects. Only the shared_ptr implementation will be reviewed; however, a raw pointer and a combination of raw pointer, shared_ptr, and unique_ptr implementations could be developed.

No “code” is shown in this post; that is left for the detailed posts.

Advertisements

5 thoughts on “Implementing Parent-Child and Similar Relationships

  1. Pingback: Parent – Child Implementation: Raw Pointers | Using C++

  2. Pingback: Parent – Child Implementation: shared_ptr | Using C++

  3. Pingback: Parent – Child Implementation: unique_ptr | Using C++

  4. Pingback: Review of Parent – Child and Multi-Level Parent – Child Implementations | Using C++

  5. Pingback: Taking Out The Garbage | Jim's Adventures in Programming

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s