<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Diamond of Death?]]></title><description><![CDATA[<pre><code class="language-cpp">struct virtual_base {
   virtual void foo() = 0;
   ~virtual_base() = default;
};

struct bar : virtual_base { };
struct foobar : virtual_base { };

struct derived : bar, foobar { };
</code></pre>
<p>Bekomme ich hier wegen des <code>vptrs</code> oder der <code>vtable</code> in der Base-Klasse einen Diamond of Death? Muss ich dann Virtuelle Vererbung bei <code>derived</code> nutzen?</p>
]]></description><link>https://www.c-plusplus.net/forum/topic/332853/diamond-of-death</link><generator>RSS for Node</generator><lastBuildDate>Mon, 27 Apr 2026 10:41:50 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/332853.rss" rel="self" type="application/rss+xml"/><pubDate>Tue, 26 May 2015 09:26:22 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to Diamond of Death? on Tue, 26 May 2015 09:26:22 GMT]]></title><description><![CDATA[<pre><code class="language-cpp">struct virtual_base {
   virtual void foo() = 0;
   ~virtual_base() = default;
};

struct bar : virtual_base { };
struct foobar : virtual_base { };

struct derived : bar, foobar { };
</code></pre>
<p>Bekomme ich hier wegen des <code>vptrs</code> oder der <code>vtable</code> in der Base-Klasse einen Diamond of Death? Muss ich dann Virtuelle Vererbung bei <code>derived</code> nutzen?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2454783</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2454783</guid><dc:creator><![CDATA[Diamant]]></dc:creator><pubDate>Tue, 26 May 2015 09:26:22 GMT</pubDate></item><item><title><![CDATA[Reply to Diamond of Death? on Tue, 26 May 2015 11:15:01 GMT]]></title><description><![CDATA[<p>Diamant schrieb:</p>
<blockquote>
<p>Bekomme ich hier wegen des <code>vptrs</code> oder der <code>vtable</code> in der Base-Klasse einen Diamond of Death?</p>
</blockquote>
<p>Das sind Implementierungsdetails virtueller Funktionen und daher für eventuelle Probleme irrelevant.</p>
<p>Grundsätzlich gibt's für virtuelle Funktionen die selben Probleme wie für &quot;normale&quot;. Zusätzlich kannst du sie in derived nicht überschreiben, da nicht klar ist, welche dann gemeint ist.</p>
<p>In deinem konkreten Beispiel treten keine Probleme auf, außer dass man derived nicht instanziieren kann.</p>
<p>Dein Destruktor in virtual_base ist sinnlos. Er sollte doch wohl virtuell sein.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2454790</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2454790</guid><dc:creator><![CDATA[manni66]]></dc:creator><pubDate>Tue, 26 May 2015 11:15:01 GMT</pubDate></item><item><title><![CDATA[Reply to Diamond of Death? on Tue, 26 May 2015 11:15:18 GMT]]></title><description><![CDATA[<p>Dein jetziger Code verwendet die &quot;Normale Mehrfachvererbung&quot;, s. <a href="http://de.wikipedia.org/wiki/Diamond-Problem" rel="nofollow">Diamond-Problem</a>, d.h. ein Objekt vom Typ &quot;derived&quot; hat dann intern zwei &quot;virtual_base&quot;-Objekte.<br />
Erst durch virtuelle Vererbung entsteht die &quot;Diamond-Vererbung&quot;, d.h. &quot;bar&quot; und &quot;foobar&quot; teilen sich dann ein &quot;virtual_base&quot;-Objekt.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2454792</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2454792</guid><dc:creator><![CDATA[Th69]]></dc:creator><pubDate>Tue, 26 May 2015 11:15:18 GMT</pubDate></item><item><title><![CDATA[Reply to Diamond of Death? on Tue, 26 May 2015 13:03:39 GMT]]></title><description><![CDATA[<p>Hm, also brauche ich wohl virtuelle Vererbung dafür.<br />
Was ist besser: Code-Duplizierung (ca. 100 Zeilen), da ich Vererbung nutze, um selbige zu vermeiden und da es mit der &quot;ist-ein&quot;-Beziehung sematisch auch passt <strong>oder</strong> Virtuelle Vererbung in Kauf nehmen?</p>
<p>Die Duplizierung würde ich dann so aufbrechen:</p>
<pre><code class="language-cpp">struct A { };
struct D1 : A { };
struct D2 : A { };

struct D21 : D2 { /* wiederhole hier Code aus D1 */ }

// vs.

struct D1 : virtual A { };
struct D2 : virtual A { };
struct D21 : D1, D2 { };
</code></pre>
<p>A soll keine Membervariablen, aber rein-virtuelle Memberfunktionen haben.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2454799</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2454799</guid><dc:creator><![CDATA[Diamant]]></dc:creator><pubDate>Tue, 26 May 2015 13:03:39 GMT</pubDate></item><item><title><![CDATA[Reply to Diamond of Death? on Tue, 26 May 2015 13:09:48 GMT]]></title><description><![CDATA[<p>In 95% der Fälle gibt's ein andere Entwurfsmuster, welches das Diamond of Death schöner löst.<br />
Ansonsten musst du halt entscheiden, was dir lieber ist, Performance oder mehr weniger Code.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2454800</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2454800</guid><dc:creator><![CDATA[Mr.L]]></dc:creator><pubDate>Tue, 26 May 2015 13:09:48 GMT</pubDate></item><item><title><![CDATA[Reply to Diamond of Death? on Tue, 26 May 2015 13:20:55 GMT]]></title><description><![CDATA[<blockquote>
<p>In 95% der Fälle gibt's ein andere Entwurfsmuster, welches das Diamond of Death schöner löst.</p>
</blockquote>
<p>Zum Bleistift?<br />
Sowohl A als auch D1 werden niemals instanziiert, da beide rein virtuell sind. Instanzen von D2 und D21 hingegen gibt es. Wegen Laufzeitpolymorphie brauche ich A und D1, D1 brauche ich auch, um Template-Parameter zu verdecken:</p>
<pre><code class="language-cpp">struct A { };

struct D1 : virtual A { /* rein virtuell */ }

template &lt;typename T&gt;
struct D2 : virtual A { /* instanziierbar */ }

template &lt;typename T&gt;
struct D21 : D1, D2 { };
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/2454804</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2454804</guid><dc:creator><![CDATA[Diamant]]></dc:creator><pubDate>Tue, 26 May 2015 13:20:55 GMT</pubDate></item><item><title><![CDATA[Reply to Diamond of Death? on Tue, 26 May 2015 13:54:11 GMT]]></title><description><![CDATA[<p>Auf 95% komme ich, da ich diese Art der Abhängigkeit 1. selber noch nie gebraucht habe (und wenn ich mal gemeint habe, ich brauche virtuelle Vererbung, habe ich doch noch ein anderes Entwurfsmuster gefunden) und 2., da du wenn du googelst &quot;How to solve a Diamond of Death&quot; du immer jemanden findest, der dir rät, ein anderes Entwursmuster zu suchen.<br />
Wenn du keines findest, musst halt dynamisch binden.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2454809</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2454809</guid><dc:creator><![CDATA[Mr.L]]></dc:creator><pubDate>Tue, 26 May 2015 13:54:11 GMT</pubDate></item><item><title><![CDATA[Reply to Diamond of Death? on Tue, 26 May 2015 16:58:16 GMT]]></title><description><![CDATA[<p>@Diamant<br />
Um ein anderes Design vorschlagen zu können, muss man den konkreten Anwendungsfall kennen <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f609.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--winking_face"
      title=";)"
      alt="😉"
    /><br />
A, D1, D2 und D21 sind dazu viel zu abstrakt.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2454818</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2454818</guid><dc:creator><![CDATA[hustbaer]]></dc:creator><pubDate>Tue, 26 May 2015 16:58:16 GMT</pubDate></item><item><title><![CDATA[Reply to Diamond of Death? on Thu, 28 May 2015 18:45:55 GMT]]></title><description><![CDATA[<p>Keine Ahnung, was ihr wissen wollt. Wie würdet ihr denn das modellieren bzw. die Mehrfachvererbung aufheben:</p>
<pre><code class="language-cpp">// Virtuelle Destruktoren mal weggelassen...
struct Objekt { virtual void fun() = 0; };
struct Waffe : Objekt { void angreifen(); }; // Zum Glück ist der Typ nicht instanziierbar
struct Schneidewerkzeug : Objekt { 
   void fun() override;
   void klinge_wechseln();
};
struct Messer : Waffe, Werkzeug { }; // Mit einem Messer kann man nun mal angreifen, man kann es aber seine Klinge wechseln
</code></pre>
<p>Objekt und Waffe brauche ich als polymorphe Zeiger, werden aber nie instanziiert.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2455042</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2455042</guid><dc:creator><![CDATA[Diamant]]></dc:creator><pubDate>Thu, 28 May 2015 18:45:55 GMT</pubDate></item><item><title><![CDATA[Reply to Diamond of Death? on Thu, 28 May 2015 19:50:48 GMT]]></title><description><![CDATA[<p>Diamant schrieb:</p>
<blockquote>
<p>Keine Ahnung, was ihr wissen wollt.</p>
</blockquote>
<p>Na einen konkreten Fall. Idealerweise einen nicht erfundenen. Und idealerweise ohne Dummy-Funktionsnamen ala &quot;fun&quot; so dass man keine Ahnung für was sie stehen sollen.<br />
Keine Ahnung was da unklar sein könnte. <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f642.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--slightly_smiling_face"
      title=":)"
      alt="🙂"
    /></p>
<p>Diamant schrieb:</p>
<blockquote>
<p>Wie würdet ihr denn das modellieren bzw. die Mehrfachvererbung aufheben:<br />
(...)<br />
Objekt und Waffe brauche ich als polymorphe Zeiger, werden aber nie instanziiert.</p>
</blockquote>
<p>Da gibt's mehrere Möglichkeiten.</p>
<ol>
<li>
<p>Mehrfachvererbung gar nicht aufheben, nix weiter machen.<br />
Je nachdem was <code>Objekt</code> enthält und was <code>fun()</code> macht kann es egal sein dass es mehrere Kopien von <code>Objekt</code> gibt. Wenn <code>Objekt</code> keine Membervariablen hat ist das oft der Fall.<br />
COM z.B. verwendet keine virtuelle Vererbung, dafür aber oft mehrfachvererbung. Die Klasse <code>IUnknown</code> wird dabei z.B. sehr oft vielfach vererbt.</p>
</li>
<li>
<p><code>Waffe</code> und <code>Schneidewerkzeug</code> müssen nicht unbedingt von <code>Objekt</code> erben. Die Regel dass alles was von <code>Waffe</code> und/oder <code>Schneidewerkzeug</code> abgeleitet ist auch von <code>Objekt</code> abgeleitet sein muss reicht völlig aus. Wenn man dann nen <code>Waffe*</code> hat aber nen <code>Objekt*</code> braucht muss man halt <code>dynamic_cast</code> verwenden.</p>
</li>
</ol>
<p>Um beurteilen zu können was mehr Sinn macht müsste man aber wissen was <code>Objekt</code> alles enthält/ist/kann.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2455049</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2455049</guid><dc:creator><![CDATA[hustbaer]]></dc:creator><pubDate>Thu, 28 May 2015 19:50:48 GMT</pubDate></item><item><title><![CDATA[Reply to Diamond of Death? on Thu, 28 May 2015 20:04:18 GMT]]></title><description><![CDATA[<p>Was hälst du von type erasure bzw. ich nenne sie hier einfach mal &quot;external polymorphie&quot;.</p>
<pre><code>struct Objekt { virtual void fun() = 0; };
struct Messer : Objekt
{
    void fun() override;
    void klinge_wechseln();
    void angreifen();
};

class Schneidewerkzeug
{
public:
    template &lt;class T&gt;
    Schneidewerkzeug(T &amp;obj)
    : fun_({](Objekt &amp;obj){static_cast&lt;T&amp;&gt;(obj).klinge_wechseln();}), obj_(obj) {}

    void klinge_wechseln()
    {
        fun_(*obj_);
    }

private:
   using function = void(*)(Objekt &amp;obj);
   function fun_;
   Objekt *obj_;
};

// Analog für Waffe
</code></pre>
<p>Schneidewerkzeug kann nun Messer und jede andere Klasse derived from Objekt nehmen, die die Funktion klinge_wechseln() anbietet.<br />
Das einzige Problem hierbei ist, dass du nun bei einer Sammlung von Objekt Pointern, sie manuell zu ihrem echten Typen casten musst, wenn du welche erzeugst.<br />
Allerdings gibt es ein ähnliches auch mit deinem bisherigen Ansatz.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2455050</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2455050</guid><dc:creator><![CDATA[Nathan]]></dc:creator><pubDate>Thu, 28 May 2015 20:04:18 GMT</pubDate></item><item><title><![CDATA[Reply to Diamond of Death? on Thu, 28 May 2015 20:20:34 GMT]]></title><description><![CDATA[<p>Für die Formatierung des Ctors (nebenbei: Tippfehler, <code>fun_({](Objekt</code> muss <code>fun_([](Objekt</code> heissen) würd ich dir, wärst du ein Mitarbeiter in meiner Abteilung, nen ordentlichen Rüffel verpassen.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2455055</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2455055</guid><dc:creator><![CDATA[hustbaer]]></dc:creator><pubDate>Thu, 28 May 2015 20:20:34 GMT</pubDate></item><item><title><![CDATA[Reply to Diamond of Death? on Thu, 28 May 2015 21:19:56 GMT]]></title><description><![CDATA[<p>Jaa, ich mir auch. Mache ich normalerweise auch schöner.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2455064</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2455064</guid><dc:creator><![CDATA[Nathan]]></dc:creator><pubDate>Thu, 28 May 2015 21:19:56 GMT</pubDate></item><item><title><![CDATA[Reply to Diamond of Death? on Fri, 29 May 2015 11:25:48 GMT]]></title><description><![CDATA[<p>@Diamant: such mal nach &quot;component based design/architecture&quot; (bzw. &quot;component based game engine&quot;). Der Ansatz mittels Mehrfachvererbung ist hier viel zu unflexibel, daher ist man auf den komponentenbasierten Ansatz gekommen.</p>
<p>Edit:<br />
Hier noch ein Link dazu: <a href="http://stackoverflow.com/questions/1901251/component-based-game-engine-design" rel="nofollow">Component based game engine design</a></p>
]]></description><link>https://www.c-plusplus.net/forum/post/2455116</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2455116</guid><dc:creator><![CDATA[Th69]]></dc:creator><pubDate>Fri, 29 May 2015 11:25:48 GMT</pubDate></item></channel></rss>