2

How should one approach composition instead of inheritance? Consider the following class:

class GameObject {...};

class Sprite {
public:
    void changeImage(...);
};

class VisibleGameObject: public Sprite, public GameObject {};

class VisibleGameObject : public GameObject {
    protected:
        Sprite m_sprite;
};

The first VisibleGameObject class uses inheritance. Multiple inheritance. Does not looks good. Second one is what i would like to use, but it won't allow me to access Sprite's API like this:

VisibleGameObject man;
man.changeImage();

How can that be accomplished without inheritance (or code duplication)?

EDIT: I do know I can just use inheritance or make m_sprite a public member and I can't access the Sprite class because it's private. That's the point, the question is about the best way to change a VisibleGameObject's Sprite, following the rules of data encapsulation.

Délisson Junio
  • 1,296
  • 4
  • 21
  • 43
  • you cannot access Sprite's methods like that. Sprite's methods can be invoked through Sprite's objects only. Also, You would like to make changeImange() `public` so that derived classes can access them. – A. K. Mar 22 '13 at 04:01
  • I don't think `friend` is going to change much. As for OP's question, it can't. You'll either have to resort to multiple inheritance (which is not necessarily always bad), or re-write wrapper methods yourself. – Nbr44 Mar 22 '13 at 04:03
  • @Nbr44, I overlooked the last couple of lines and hence my incorrect comment. Sorry for confusion. – A. K. Mar 22 '13 at 04:04

3 Answers3

3

I think you are still one step behing "composition over inheritance" mindset. The base class should know what to composite. To change image, you should change sprite instance, you shouldn't provide interface of composed instances. For example:

class GameObject {
public:
    // you can choose public access or getters and setters, it's your choice
    Sprite sprite;
    PhysicalBody body;
};

object = GameObject();
object.sprite = graphicalSystem.getSpriteFromImage("image.png");
// or if you prefer setters and getters
object.setSprite(sprite);

More generally GameObject should contain instances (or pointers to instances, depends on your implementation) of base class Component. It makes sense to use inheritance in this case, because this way they can be in one storage like std::map. For example:

class Component {
    // ...
};

class Sprite : public Component {
    //...
};

class PhysicalBody : public Component {
    //...
};

class GameObject {
protected:
    std::map<std::string, Component*> components;
    //...
public:
    Component* getComponent(const std::string& name) const;
    void setComponent(const std::string& name, Component* component);
    //...
};

For component creation and rendering in main loop use Systems. For example GraphicalSystem knows all instances of Sprite it has created and while rendering it renders only sprites attached to some GameObject instance. Detached component can be garbage collected. Information about position and size might be part of the GameObject or it might be a component "physical".

The best way to understand it is to write your own prototype or to check existing implementations (Artemis, Unity 3D and many others). For more information see Cowboy programming: Evolve Your Hierarchy or try to find Entity/component system.

Stan Prokop
  • 5,579
  • 3
  • 25
  • 29
2

First of all, the alternative for composition is private inheritance (and not public one) since both model a has-a relationship.

The important question is how can we expose Sprite public members (e.g. changeImage) to VisibleGameObject clients? I present the 4 methods that I know:

(Private) inheritance

I understand that you want to avoid (multiple) inheritance, but for the sake of completeness, I present one suggestion based on private inheritance:

class VisibleGameObject: private Sprite, public GameObject {
...
};

In this case VisibleGameObject privately derives from Sprite. Then users of former cannot access any member of the latter (as if it it were a private member). In particular, Sprite's public and protected members are hidden to VisibleGameObject clients.

Had the inheritance been public, then all Sprite's public and protected members would be exposed by VisibleGameObject to its clients. With private inheritance we have a finer control of which methods should be exposed through using declarations. For instance, this exposes Sprite::changeImage:

class VisibleGameObject1: private Sprite, public GameObject {
public:
    using Sprite::changeImage;
...
};

Forwarding methods

We can give to VisibleGameObject public methods that forward the call to m_sprite as show below.

class VisibleGameObject2: public GameObject {
public:
    void changeImage() {
        m_sprite.changeImage();
    }
private:
    Sprite m_sprite;
...
};

I believe this is the best design, especially as far as encapsulation is concerned. However, it might require a lot of typing in respect to other alternatives.

Structure dereference operator

Even plain old C provides types that exposes another type's interface as if it was its own: pointers.

Indeed, suppose that p is of type Sprite*. Then by using the structure dereference operator -> we can access members of Sprite (pointed by p) as shown below.

p->changeImage();

C++ allows us to endow classes with customised struct dereference operators (a feature well used by smart pointers). Our example becomes:

class VisibleGameObject3 : public GameObject {
public:
    Sprite* operator ->() {
        return &m_sprite;
}
private:
    Sprite m_sprite;
...
};

and

VisibleGameObject v;
v->changeImage();

Although convenient, this method has many flaws:

  1. As for public inheritance, this approach doesn't give a fine control over which Sprite public members should be exposed.
  2. It works only for one member (that is, you cannot use the same trick to expose two members interfaces).
  3. It messes up with the interface. Indeed, consider for instance that VisualGameObject has a method doSomething(). Then, to call this method on an object v one should do v.doSomething() whereas to call changeImage() one should uses v->changeImage(). This is confusing.
  4. It makes VisibleGameInterface to look like a smart pointer. This is semantically wrong!

C++11 Wrapper Pattern

Finally, there's Sutter's C++11 Wrapper Pattern (watch his presentation, specifically the second slide of page 9):

class VisibleGameObject4 : public GameObject {
private:
    Sprite m_sprite;
public:
    template <typename F>
    auto operator()(F f) -> decltype(f(m_sprite)) {
        return f(m_sprite);
    }
};

Clients use it this way:

VisibleGameObject4 v4;
v4( [](Sprite& s) { return s.changeImage(); } );

As we can see, compared to the forwarding methods approach this transfer the burden of typing from the class writter to the class clients.

Cassio Neri
  • 19,583
  • 7
  • 46
  • 68
0

It looks like you are trying to directly access Sprite's function without referencing it first. Try this:

man.m_sprite.changeImage() ;

Note that m_sprite and changeImage() should be public for you to do this. Otherwise use a public accessor function to manipulate private class members.

Justin H.
  • 143
  • 8