• Announcements

    • khawk

      Download the Game Design and Indie Game Marketing Freebook   07/19/17

      GameDev.net and CRC Press have teamed up to bring a free ebook of content curated from top titles published by CRC Press. The freebook, Practices of Game Design & Indie Game Marketing, includes chapters from The Art of Game Design: A Book of Lenses, A Practical Guide to Indie Game Marketing, and An Architectural Approach to Level Design. The GameDev.net FreeBook is relevant to game designers, developers, and those interested in learning more about the challenges in game development. We know game development can be a tough discipline and business, so we picked several chapters from CRC Press titles that we thought would be of interest to you, the GameDev.net audience, in your journey to design, develop, and market your next game. The free ebook is available through CRC Press by clicking here. The Curated Books The Art of Game Design: A Book of Lenses, Second Edition, by Jesse Schell Presents 100+ sets of questions, or different lenses, for viewing a game’s design, encompassing diverse fields such as psychology, architecture, music, film, software engineering, theme park design, mathematics, anthropology, and more. Written by one of the world's top game designers, this book describes the deepest and most fundamental principles of game design, demonstrating how tactics used in board, card, and athletic games also work in video games. It provides practical instruction on creating world-class games that will be played again and again. View it here. A Practical Guide to Indie Game Marketing, by Joel Dreskin Marketing is an essential but too frequently overlooked or minimized component of the release plan for indie games. A Practical Guide to Indie Game Marketing provides you with the tools needed to build visibility and sell your indie games. With special focus on those developers with small budgets and limited staff and resources, this book is packed with tangible recommendations and techniques that you can put to use immediately. As a seasoned professional of the indie game arena, author Joel Dreskin gives you insight into practical, real-world experiences of marketing numerous successful games and also provides stories of the failures. View it here. An Architectural Approach to Level Design This is one of the first books to integrate architectural and spatial design theory with the field of level design. The book presents architectural techniques and theories for level designers to use in their own work. It connects architecture and level design in different ways that address the practical elements of how designers construct space and the experiential elements of how and why humans interact with this space. Throughout the text, readers learn skills for spatial layout, evoking emotion through gamespaces, and creating better levels through architectural theory. View it here. Learn more and download the ebook by clicking here. Did you know? GameDev.net and CRC Press also recently teamed up to bring GDNet+ Members up to a 20% discount on all CRC Press books. Learn more about this and other benefits here.
Sign in to follow this  
Followers 0
BurrickSlayer

Composite pattern with parent pointer in C++

7 posts in this topic

Hello all,

I wanted to use the composite pattern in C++ but I encountered a problem in doing so.

My code looks like that:
 
class Component
{
    protected:
    
        Component* parent = nullptr;
};

class Leaf : public Component
{};

class Composite : public Component
{
    public:
    
        typedef std::unique_ptr<Component> ComponentPtr;
        
    public:
    
        void addChild(ComponentPtr child)
        {
            child->parent = this;
            // ...
        }
        
        auto removeChild(const Component& child) -> ComponentPtr;
};
 
The problem is that in the addChild method the protected parent member can't be accessed. I just have learned that an instance A can access the protected members of an instance B if and only if A and B are of the same type or B is derived from A. So the code shown above doesn't work for obvious reasons.

Now I ask myself how to solve the problem of not being able to access the parent member. Currently I can think of some possibilities:
  • Use a friend class/function/method to access the parent member.
  • Make the parent member public or provide a public getter/setter method.
  • Don't use the composite pattern. Instead have only a Component class that has both a parent and children.
I can't decide on the first option because I've hardly used friends in C++ so far.

I'm not too fond of the second option because setting the parent should not be part of the public API.

When using the third option every component would be a composite. Whether this is to be considered a bad thing probably depends on what the code is used for. In my case it wouldn't be so bad. If an object isn't supposed to have children I just won't add any.

What do you think? Are there any other alternatives?
 
Edit:
 
Unfortunately I have left out some relevant implementation details. As this caused some misunderstandings  I would like to add the missing details here:
 
class Composite : public Component
{
    /* some code ommited */

    public:
    
        void addChild(ComponentPtr child)
        {
            child->parent = this;
            children.push_back(std::move(child));
        }

        /* some code ommited */
        
    private:

        std::vector<ComponentPtr> children;
};
Edited by BurrickSlayer
0

Share this post


Link to post
Share on other sites

A protected static function in Component would be able to access whatever you need in Component and be called from any Component.

static void SetParentOfChild(Component* child, Component* parent)
{
    child->parent = parent;
}

Note: I don't think you should be passing unique_ptr around by value. Would would addChild use a smart pointer and removeChild a const reference? You have to modify the child's parent member in both situations, right?

Edited by Pink Horror
1

Share this post


Link to post
Share on other sites
@Pink Horror



A protected static function in Component would be able to access whatever you need in Component and be called from any Component.

 
Aah, thanks, I haven't thought of that. If I go with the composite pattern this will be a good option for setting the parent pointers.
 

Note: I don't think you should be passing unique_ptr around by value. Would would addChild use a smart pointer and removeChild a const reference? You have to modify the child's parent member in both situations, right?

 
I have left out some implementation details because I didn't consider them important at the time of writing my post. But now I see that the missing details have caused some misunderstandings. I'm sorry for that. I edited my first post accordingly.

The children are stored in a vector member of the composite: std::vector<ComponentPtr> children;
So this is what the addChild method actually looks like:
 
void addChild(ComponentPtr child)
{
    child->parent = this;
    children.push_back(std::move(child));
}

The unique_ptr is passed by value to show that the ownership of the component is transferred to the composite.

And yes, the removeChild method also modifies the child's parent member. This is done by an iterator returned by std::find_if, though, so the passed const reference stays untouched. I hope this clears things up.
 
But now as you say it I'm not sure anymore if declaring the reference const was a good idea. The child is modified after all, just by other means than using the passed reference.


@Hodgman
 

Do you need the parent pointer?
You can reverse the relationship and use composite-has-many-children, not component-has-a-parent.

 
Unfortunately I have left out implementation details in my first post because I considered them not important at the time of writing. That was a mistake. There are more details about what the Composite class actually looks like in my answer addressed to Pink Horror (and in the edit section of my first post).

So to be precise there is a bidirectional relationship between composites and their children: composite-has-many-children and component-has-a-parent.
The parent pointer is not absolutely needed indeed. It's just convenient to know a child's parent as it makes removing nodes easier. If the parents are unknown I need to iterate the whole structure in order to find the vector that containes the node to be removed.


-----

I'm not sure whether the composite pattern is the right choice in my particular case. Being able to treat components and composites the same is negligible for me because a visitor is used for iteration. Most components will be composites anyway so having a children vector in the leafs would be negligible too. Perhaps I'll just have a common base class for components that has both a parent and a children member. I need to think about that.

Thanks for your suggestions!
0

Share this post


Link to post
Share on other sites

The children are stored in a vector member of the composite: std::vector children;
So this is what the addChild method actually looks like:
 
void addChild(ComponentPtr child)
{
child->parent = this;
children.push_back(std::move(child));
}
The unique_ptr is passed by value to show that the ownership of the component is transferred to the composite.

 

In order for child to be passed in, it has to be copied, which shouldn't compile. unique_ptr is not copy constructible or copy assignable. You're moving out of a temporary unique_ptr instead of the real one.

Edited by Pink Horror
0

Share this post


Link to post
Share on other sites
Children can be moved into the composites, so there is no copy construction required:
 
// Option 1
composite.addChild(Composite::ComponentPtr(new Component()));

// Option 2
Composite::ComponentPtr component(new Component());
// ... do some stuff with component ...
composite.addChild(std::move(component));

I like it because I think it's quite expressive this way and self-documents the transfer of ownership.
1

Share this post


Link to post
Share on other sites

My first choice would be avoiding parent pointers, because both normal component operations (e.g. update or draw yourself and your children recursively) and "special" operations (e.g. delete a Component but place its children, if present, in a sensible Composite) shouldn't need them, and placing all Components in a single structural hierarchy seems wrong (what if you need different groupings for the same objects, e.g. pieces of articulated objects grouped by position for drawing and collision detection and by "limb" connectivity for physical simulation and animation?).

 

Can you clarify what you are unable to do without parent pointers? For example, why do you want to actually delete Components given only a pointer to them? You can instead set a "deleted" flag on the component, which should be good enough for the purpose of pretending the component doesn't exist, and later visit components recursively to delete their flagged children.

 

I'm not sure about a Composite abstract class a it appears in your code sample: it is almost trivial, and there can be many other Composite types beyond those with an array containing an arbitrary number of undifferentiated children. 

 

Another bad thing is the use of unique_ptr and of containers that own child Components. It's another enemy of multiple Composite hierarchies and of flexible destruction of Components; a std::vector or individual variables of type Component* would let you move child components to other composites or delete them as you need when you delete or recycle a composite.

1

Share this post


Link to post
Share on other sites

Can you clarify what you are unable to do without parent pointers? For example, why do you want to actually delete Components given only a pointer to them? You can instead set a "deleted" flag on the component, which should be good enough for the purpose of pretending the component doesn't exist, and later visit components recursively to delete their flagged children.

The parent pointers aren't necessarily needed and now I'll try to do without them. I had them mainly for convenience so I could remove a component from its composite more easily.
In any case the deleted flag is a good idea and I'll have this implemented. Such a flag should also work nice along with std::remove_if. Thanks for your suggestion.

 

Another bad thing is the use of unique_ptr and of containers that own child Components. It's another enemy of multiple Composite hierarchies and of flexible destruction of Components; a std::vector or individual variables of type Component* would let you move child components to other composites or delete them as you need when you delete or recycle a composite.

I agree with you that a unique_ptr wouldn't be a good choice for components that are shared by multiple composites. My sample code was written with unshared components in mind (a simple tree structure), so that's why I decided for unique_ptr.
0

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0