Thread: Making child object access parent - best design?

  1. #1
    Ex scientia vera
    Join Date
    Sep 2007
    Posts
    477

    Making child object access parent - best design?

    I'm writing a simple graphical application in SDL, and trying to design it in a nice OO manner.

    I have a World class which basically contains the SDL_Surfaces for the background and screen and so on, and the World class contains a vector of pointers to a class Object, which is a pure abstract class which contains basic functionality for all objects.

    The objects in the world are required to access some members of its World. One example is are the functions RealToEffective and EffectiveToReal, which are basically used to translate objects coordinates from their real coordinates to the effective coordinates(For a lack of a better term).
    That is, the bottom left corner of the window is the origin(0,0) in "effective coordinates", as that's how the world is, but in SDL, the origin in the top left.

    Code looks something like this:

    Code:
    class World
    {
    public:
         void AddObject(Object *obj);
         void AddObject(boost::shared_ptr<Object> Obj);
         Coord RealToEffective(int x, int y);
         Coord EffectiveToReal(int x, int y);
    private:
         std::vector<boost::shared_ptr<Object>> _objects;
    };
    Currently, I'm simply passing each object a reference of the world it's in through the constructor, but I don't know, that doesn't seem like the best way to do it for some reason.

    I'm kind of new to all these heavily OO designs, but I still love to do this. How would you guys solve this? Is there any proper way to do it, and is there something bad about doing it the way I'm currently doing it?
    "What's up, Doc?"
    "'Up' is a relative concept. It has no intrinsic value."

  2. #2
    Registered User
    Join Date
    Oct 2006
    Posts
    250
    I usually reason this out as follows. Since there is just one 'World' or 'Universe' or whatever you want to call it that all other objects have access to and can interact with it makes sense to me to make this 'World' object a singleton. Thereby you effectively prevent any other 'World's from being created and you can access the world without having to resort to tricks such as passing in the world as an 'Object's constructor argument.

  3. #3
    Ex scientia vera
    Join Date
    Sep 2007
    Posts
    477
    Quote Originally Posted by MWAAAHAAA View Post
    I usually reason this out as follows. Since there is just one 'World' or 'Universe' or whatever you want to call it that all other objects have access to and can interact with it makes sense to me to make this 'World' object a singleton. Thereby you effectively prevent any other 'World's from being created and you can access the world without having to resort to tricks such as passing in the world as an 'Object's constructor argument.
    That sounds logical to me. I better research the singleton pattern then.

    Thanks!
    "What's up, Doc?"
    "'Up' is a relative concept. It has no intrinsic value."

  4. #4
    verbose cat
    Join Date
    Jun 2003
    Posts
    209
    Another option would be to make them static member functions. You would call them as
    Code:
    Coord c = World::RealToEffective(x,y);
    Coord d = World::EffectiveToReal(x,y);
    And they would be declared in the class declaration as
    Code:
    static Coord RealToEffective(int x, int y);
    static Coord EffectiveToReal(int x, int y);
    and defined the same way you define other member functions
    Code:
    Coord World::RealToEffective(int x, int y) { /* conversion done here*/ }
    Coord World::EffectiveToReal(int x, int y) { /* conversion done here*/ }
    Making the functions static in this way keeps them in the World class, as they are directly related to the functionality of the World, while allowing you to call the functions independant of any World instance.

    The caveat is that they can not access any non-static World class data without having an instance of the class, just like a non-member function. So if they use some data from the World class to do the conversion then this would not work.
    abachler: "A great programmer never stops optimizing a piece of code until it consists of nothing but preprocessor directives and comments "

  5. #5
    Ex scientia vera
    Join Date
    Sep 2007
    Posts
    477
    Quote Originally Posted by jEssYcAt View Post
    Another option would be to make them static member functions. You would call them as
    Code:
    Coord c = World::RealToEffective(x,y);
    Coord d = World::EffectiveToReal(x,y);
    And they would be declared in the class declaration as
    Code:
    static Coord RealToEffective(int x, int y);
    static Coord EffectiveToReal(int x, int y);
    and defined the same way you define other member functions
    Code:
    Coord World::RealToEffective(int x, int y) { /* conversion done here*/ }
    Coord World::EffectiveToReal(int x, int y) { /* conversion done here*/ }
    Making the functions static in this way keeps them in the World class, as they are directly related to the functionality of the World, while allowing you to call the functions independant of any World instance.

    The caveat is that they can not access any non-static World class data without having an instance of the class, just like a non-member function. So if they use some data from the World class to do the conversion then this would not work.
    That's just it - the conversion uses the width and height of the world for calculations. A singleton will probably work. That, or assigning the world to some member of an object on its insertion - kind of removes the redundant code and is less error prone, in the case a user might pass the wrong world to an object or something.
    "What's up, Doc?"
    "'Up' is a relative concept. It has no intrinsic value."

  6. #6
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    If you want a *really* simple singleton interface, you might look into something like this.

  7. #7
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    A word of caution: are you absolutely sure that There can be only one™ world, forever? If not, then the singleton pattern is not appropriate.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  8. #8
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    There are two basic ways for coordinating data between master and slave objects.

    1. The master objects "sets" the required data into the slave via a setter method. Advantage: Decreases coupling between slave and master object, because the slave does not need to call back to the master. Disadvantage: The data exists in two locations, opening the possibility of getting out of sync (most likely due to a bug somewhere in the master).

    2. The slave objects "gets" the required data from the master via a getter method. Advantage: Eliminates risk of incoherent data, since the slave queries the master directly for the current state. Disadvantage: Increases coupling between the slave and master object, since the slave must call back to the master.

    Obviously these are mirror images of each other. Which one you select is probably going to depend on how likely you think it is that the slave object might someday be decoupled from the master and used in a different context.
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

  9. #9
    Ex scientia vera
    Join Date
    Sep 2007
    Posts
    477
    Thanks for your advice, guys.

    I'm not sure if the singleton pattern will fit, I haven't decided if I'll use this class as the whole World, or a part of the World(Like, the next 'level' or something).

    However I decide to do it, I think simply giving the slave a pointer to the World(Which makes sure that the data is always up to date) when the slave is inserted will work.

    Thanks!
    "What's up, Doc?"
    "'Up' is a relative concept. It has no intrinsic value."

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Creating a child window in a parent window
    By vopo in forum Windows Programming
    Replies: 8
    Last Post: 10-06-2007, 04:15 PM
  2. Replies: 7
    Last Post: 03-10-2004, 04:10 PM
  3. Parent/child object design
    By lyx in forum C++ Programming
    Replies: 6
    Last Post: 11-28-2003, 09:46 AM
  4. shared int between parent and child
    By rotis23 in forum C Programming
    Replies: 1
    Last Post: 02-07-2003, 08:54 AM
  5. Object Oriented Design help!! ;(
    By cpp4ever in forum C++ Programming
    Replies: 3
    Last Post: 12-03-2001, 11:16 AM