SFML community forums

Help => Graphics => Topic started by: xarxer on January 17, 2010, 03:50:20 pm

Title: Inherit or contain?
Post by: xarxer on January 17, 2010, 03:50:20 pm
Hi, I'm going to try to explain this correctly..

Let's say I have a class CEntity, like this:
Code: [Select]

class CEntity : public sf::Drawable
{
      private:
            int mX, mY;   //An entity always has a position
};


And then I have a class CObject, like this:
Code: [Select]

class CObject : public CEntity //Derived from CEntity
{
      private:
            sf::Sprite mTexture;    // An object always has a texture

      public:
            //We want to draw this object via sf::RenderWindow::Draw()
            virtual void Render(RenderTarget& Target) const
            {
                  Target.Draw(mTexture);
            }
};


Now, is this a bad thing to do?
And how should I do instead?

Let's say I call upon CObject::SetPosition(), there is no position to set?

I'm sorry if it's a bad example, but it was all that I could think of at the moment..
Title: Inherit or contain?
Post by: Nexus on January 17, 2010, 04:13:02 pm
When deciding between aggregation and inheritance, you have to know that public inheritance expresses that each derived class object is a base class object. That implies that it makes always sense to treat a derived object as a base object, and a derived class object owns all properties and provides all methods of the base class. (Note: Polymorphism isn't required in all cases you inherit, but if you need it, inheritance is the only option).

If you want only a part of the object to form the public interface, or if it is more meaningful if the class semantically has a CEntity object, choose aggregation.
Title: Inherit or contain?
Post by: xarxer on January 17, 2010, 04:40:58 pm
hmm I see your point, but still if I want an object like this:
Code: [Select]

class CObject
{
      private:

            sf::Sprite mTexture;

      public:

            void Move(float x, float y)      { mTexture.Move(x,y); }
            //Other cool functions and stuff here
};


And now I want to draw it.

Do I have to make a void Draw(sf::RenderWindow& App) function?
Title: Inherit or contain?
Post by: Laurent on January 17, 2010, 05:33:03 pm
Quote
Do I have to make a void Draw(sf::RenderWindow& App) function?

That's a good solution, I'd do the same.

Note that if you have many functions from sf::Drawable to forward, it may be easier to use private inheritance rather than aggregation. This is semantically equivalent, but private inheritance allows nice syntax shortcuts.

Code: [Select]
class CObject : private sf::Sprite
{
      public:

            using sf::Sprite::Move;
            using sf::Sprite::Rotate;
            // etc.
};
Title: Inherit or contain?
Post by: xarxer on January 17, 2010, 06:02:32 pm
hmm that seems like a good soloution Laurent..

But what is the purpose of the virtual void Render(RenderTarget& Target) const;?
Title: Inherit or contain?
Post by: Laurent on January 17, 2010, 06:48:57 pm
Quote
But what is the purpose of the virtual void Render(RenderTarget& Target) const;?

You don't have to care about this one, it is used by classes that publicly inherit from sf::Drawable.
Title: Inherit or contain?
Post by: xarxer on January 17, 2010, 11:12:47 pm
Oh very well then  :D
I thought it was there for people to use it to easily make custom classes drawable..

Keep up the good work, SFML is a really nice API :)
Title: Inherit or contain?
Post by: Nexus on January 17, 2010, 11:46:53 pm
Quote from: "xarxer"
I thought it was there for people to use it to easily make custom classes drawable..
Actually, it is. ;)

Nevertheless, that still doesn't mean that every object that can be drawn needs to inherit from sf::Drawable. One of the ways is your member function
Code: [Select]
void Object::Draw(sf::RenderWindow& Target);
An alternative would be to write a function outside your class, which takes your object as parameter and draws it. Either as a member of a class that is in charge of rendering, or as global function.
Code: [Select]
void Renderer::Draw(const Object& obj);
void DrawObject(sf::RenderWindow& Target, const Object& obj);

Just to show you some different approaches. What fits best for you, depends on your design preferences. I personally like the Renderer::Draw() way because it nicely separates graphics from logics.