Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>First of all, the <a href="http://www.parashift.com/c++-faq/priv-inherit-like-compos.html" rel="nofollow">alternative for composition is private inheritance</a> (and not public one) since both model a <em>has-a</em> relationship.</p> <p>The important question is how can we expose <code>Sprite</code> public members (e.g. <code>changeImage</code>) to <code>VisibleGameObject</code> clients? I present the 4 methods that I know:</p> <h2>(Private) inheritance</h2> <p>I understand that you want to avoid (multiple) inheritance, but for the sake of completeness, I present one suggestion based on private inheritance:</p> <pre><code>class VisibleGameObject: private Sprite, public GameObject { ... }; </code></pre> <p>In this case <code>VisibleGameObject</code> privately derives from <code>Sprite</code>. Then users of former cannot access any member of the latter (as if it it were a private member). In particular, <code>Sprite</code>'s public and protected members are hidden to <code>VisibleGameObject</code> clients.</p> <p>Had the inheritance been public, then <strong>all</strong> <code>Sprite</code>'s public and protected members would be exposed by <code>VisibleGameObject</code> to its clients. With private inheritance we have a finer control of which methods should be exposed through using declarations. For instance, this exposes <code>Sprite::changeImage</code>:</p> <pre><code>class VisibleGameObject1: private Sprite, public GameObject { public: using Sprite::changeImage; ... }; </code></pre> <h2>Forwarding methods</h2> <p>We can give to <code>VisibleGameObject</code> public methods that forward the call to <code>m_sprite</code> as show below.</p> <pre><code>class VisibleGameObject2: public GameObject { public: void changeImage() { m_sprite.changeImage(); } private: Sprite m_sprite; ... }; </code></pre> <p>I believe <strong>this is the best design</strong>, especially as far as encapsulation is concerned. However, it might require a lot of typing in respect to other alternatives.</p> <h2>Structure dereference operator</h2> <p>Even plain old C provides types that exposes another type's interface as if it was its own: pointers.</p> <p>Indeed, suppose that <code>p</code> is of type <code>Sprite*</code>. Then by using the structure dereference operator <code>-&gt;</code> we can access members of <code>Sprite</code> (pointed by <code>p</code>) as shown below.</p> <pre><code>p-&gt;changeImage(); </code></pre> <p>C++ allows us to endow classes with customised struct dereference operators (a feature well used by smart pointers). Our example becomes:</p> <pre><code>class VisibleGameObject3 : public GameObject { public: Sprite* operator -&gt;() { return &amp;m_sprite; } private: Sprite m_sprite; ... }; </code></pre> <p>and</p> <pre><code>VisibleGameObject v; v-&gt;changeImage(); </code></pre> <p>Although convenient, this method has many flaws:</p> <ol> <li>As for public inheritance, this approach doesn't give a fine control over which <code>Sprite</code> public members should be exposed.</li> <li>It works only for one member (that is, you cannot use the same trick to expose two members interfaces).</li> <li>It messes up with the interface. Indeed, consider for instance that <code>VisualGameObject</code> has a method <code>doSomething()</code>. Then, to call this method on an object <code>v</code> one should do <code>v.doSomething()</code> whereas to call <code>changeImage()</code> one should uses <code>v-&gt;changeImage()</code>. This is confusing.</li> <li>It makes <code>VisibleGameInterface</code> to look like a smart pointer. This is semantically wrong!</li> </ol> <h2>C++11 Wrapper Pattern</h2> <p>Finally, there's Sutter's C++11 Wrapper Pattern (watch his <a href="http://channel9.msdn.com/Shows/Going+Deep/C-and-Beyond-2012-Herb-Sutter-Concurrency-and-Parallelism" rel="nofollow">presentation</a>, specifically the second <a href="https://skydrive.live.com/?cid=f1b8ff18a2aec5c5&amp;id=F1B8FF18A2AEC5C5!1176" rel="nofollow">slide</a> of page 9):</p> <pre><code>class VisibleGameObject4 : public GameObject { private: Sprite m_sprite; public: template &lt;typename F&gt; auto operator()(F f) -&gt; decltype(f(m_sprite)) { return f(m_sprite); } }; </code></pre> <p>Clients use it this way:</p> <pre><code>VisibleGameObject4 v4; v4( [](Sprite&amp; s) { return s.changeImage(); } ); </code></pre> <p>As we can see, compared to the forwarding methods approach this transfer the burden of typing from the class writter to the class clients.</p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload