<?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[Dobule Dispatch und Alternativen]]></title><description><![CDATA[<p>Hallo,</p>
<p>ich arbeite zurzeit mit einem Freund an einem Spiel, bei dem ich (mit dem bisherigen design) periodisch nach kollisionen suche und dann bei der kollisionsbehandlung je nach typ der beteiligten objekte etwas bestimmtes mache.</p>
<p>Also ich habe ungefähr sowas an Klassen:<br />
- GameObject (Basisklasse für alle folgenden Klassen)<br />
- Enemy (Basisklasse für Gegner)<br />
- Immortal(Basisklasse für Wände/Bläcke / etc.)<br />
- Usable (Basisklasse für Powerups etc.)<br />
- und paar mehr...</p>
<p>und dann gibt es eine Reihe von konkreten Klassen, die jeweils von Enemy,Immortal,Usable oder weiteren Basisklassen ableiten.</p>
<p>Ich suche dann in einer Liste von GameObjects nach Kollisionen und wenn ich was finde mache ich ungefähr sowas:</p>
<pre><code class="language-cpp">a.collideWith(b); b.collideWith(a);
</code></pre>
<p>Und je nach typ des jeweils anderen muss dann eine von der konkreten klasse festgelegte behandlung erfolgen.</p>
<p>Bisher machen wir das so, dass ich für jede der Basisklassen eigene container nehme und dann dann kollisionen immer zwischen zwei containern checke und dann beim aufruf direkt die für die basisklasse überladene methode aufgerufen wird beim anderen objekt.</p>
<p>Alerdings erlaubt das nur spezielles verhalten für jede Basisklasse, manchmal brauch ich auch besonderes Verhalten für konkrete Klassen.</p>
<p>Bisher regeln wir das durch dynamic cast... allerdings finde ich das nicht besonders toll.<br />
Also ungefähr so:</p>
<pre><code class="language-cpp">if((a = dynamic_cast&lt;Yoshi&gt;(b))
{
   //Spezialbehandlung für Yoshi
}
</code></pre>
<p>Ich kenne die Möglichkeit double dispatch zu verwenden, aber dann muss JEDE klasse eine methode für JEDE andere klasse haben, was ich nicht besonders toll finde...<br />
Meistens sind die Behandlungen für die Basisklassen gleich.<br />
Dann hab ich mir noch überlegt, man kann sich ne virtuelle methode machen, wie<br />
getTypeId() oder die eingebauten typeinfos oder so verwenden und dann maps verwenden um auf die funktionen zu mappen.<br />
So richtig hat mich das aber auch nicht überzeugt...</p>
<p>Hat jemand Vorschläge?</p>
]]></description><link>https://www.c-plusplus.net/forum/topic/287847/dobule-dispatch-und-alternativen</link><generator>RSS for Node</generator><lastBuildDate>Wed, 19 Aug 2026 02:08:52 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/287847.rss" rel="self" type="application/rss+xml"/><pubDate>Sun, 05 Jun 2011 15:51:06 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to Dobule Dispatch und Alternativen on Sun, 05 Jun 2011 15:51:06 GMT]]></title><description><![CDATA[<p>Hallo,</p>
<p>ich arbeite zurzeit mit einem Freund an einem Spiel, bei dem ich (mit dem bisherigen design) periodisch nach kollisionen suche und dann bei der kollisionsbehandlung je nach typ der beteiligten objekte etwas bestimmtes mache.</p>
<p>Also ich habe ungefähr sowas an Klassen:<br />
- GameObject (Basisklasse für alle folgenden Klassen)<br />
- Enemy (Basisklasse für Gegner)<br />
- Immortal(Basisklasse für Wände/Bläcke / etc.)<br />
- Usable (Basisklasse für Powerups etc.)<br />
- und paar mehr...</p>
<p>und dann gibt es eine Reihe von konkreten Klassen, die jeweils von Enemy,Immortal,Usable oder weiteren Basisklassen ableiten.</p>
<p>Ich suche dann in einer Liste von GameObjects nach Kollisionen und wenn ich was finde mache ich ungefähr sowas:</p>
<pre><code class="language-cpp">a.collideWith(b); b.collideWith(a);
</code></pre>
<p>Und je nach typ des jeweils anderen muss dann eine von der konkreten klasse festgelegte behandlung erfolgen.</p>
<p>Bisher machen wir das so, dass ich für jede der Basisklassen eigene container nehme und dann dann kollisionen immer zwischen zwei containern checke und dann beim aufruf direkt die für die basisklasse überladene methode aufgerufen wird beim anderen objekt.</p>
<p>Alerdings erlaubt das nur spezielles verhalten für jede Basisklasse, manchmal brauch ich auch besonderes Verhalten für konkrete Klassen.</p>
<p>Bisher regeln wir das durch dynamic cast... allerdings finde ich das nicht besonders toll.<br />
Also ungefähr so:</p>
<pre><code class="language-cpp">if((a = dynamic_cast&lt;Yoshi&gt;(b))
{
   //Spezialbehandlung für Yoshi
}
</code></pre>
<p>Ich kenne die Möglichkeit double dispatch zu verwenden, aber dann muss JEDE klasse eine methode für JEDE andere klasse haben, was ich nicht besonders toll finde...<br />
Meistens sind die Behandlungen für die Basisklassen gleich.<br />
Dann hab ich mir noch überlegt, man kann sich ne virtuelle methode machen, wie<br />
getTypeId() oder die eingebauten typeinfos oder so verwenden und dann maps verwenden um auf die funktionen zu mappen.<br />
So richtig hat mich das aber auch nicht überzeugt...</p>
<p>Hat jemand Vorschläge?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2073656</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2073656</guid><dc:creator><![CDATA[Gast1337]]></dc:creator><pubDate>Sun, 05 Jun 2011 15:51:06 GMT</pubDate></item><item><title><![CDATA[Reply to Dobule Dispatch und Alternativen on Sun, 05 Jun 2011 16:00:05 GMT]]></title><description><![CDATA[<p>Gast1337 schrieb:</p>
<blockquote>
<p>Hat jemand Vorschläge?</p>
</blockquote>
<p>Mein Vorschlag: Einfach beim normalen Double Dispatching bleiben.</p>
<p>Aber Du wirst mecp lesen wollen. Da läßt er sich in aller Ausführlichkeit zu diesem Themenkomplex aus.<br />
<a href="http://www.amazon.de/Effektiv-programmieren-Verbesserung-Programme-Entw%C3%BCrfe/dp/3827312752" rel="nofollow">http://www.amazon.de/Effektiv-programmieren-Verbesserung-Programme-Entwürfe/dp/3827312752</a></p>
]]></description><link>https://www.c-plusplus.net/forum/post/2073662</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2073662</guid><dc:creator><![CDATA[volkard]]></dc:creator><pubDate>Sun, 05 Jun 2011 16:00:05 GMT</pubDate></item><item><title><![CDATA[Reply to Dobule Dispatch und Alternativen on Sun, 05 Jun 2011 16:01:08 GMT]]></title><description><![CDATA[<p>Double-Dispatching ist doch schon ganz gut. Höchstwahrscheinlich kannst du da aber gut was reduzieren, z.B. steckst du die Kollisionen in die (oder spezielle) Formen und nicht in die Spielobjekte.</p>
<p>In typischer 3D-Umgebung hat man ja Flächen (Ebenen, rechteckige, radiale, ...), Polygonnetze und geometrische Körper; dann per Komposition auch Zusammengesetztes. Hier musst du dann &quot;nur noch&quot; die einzelnen Formen kollidieren lassen (also Fläche&lt;-&gt;Polygonnetz, Kugel&lt;-&gt;Quader, ...), das ist noch handhabbar per Double-Dispatching.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2073663</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2073663</guid><dc:creator><![CDATA[Vorschläger]]></dc:creator><pubDate>Sun, 05 Jun 2011 16:01:08 GMT</pubDate></item><item><title><![CDATA[Reply to Dobule Dispatch und Alternativen on Sun, 05 Jun 2011 16:02:08 GMT]]></title><description><![CDATA[<p>Ja, ich schlage dir einen Blick in unser <a href="http://magazin.c-plusplus.net/artikel/Multimethoden" rel="nofollow">Magazin</a> vor <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="😉"
    /></p>
]]></description><link>https://www.c-plusplus.net/forum/post/2073665</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2073665</guid><dc:creator><![CDATA[CStoll]]></dc:creator><pubDate>Sun, 05 Jun 2011 16:02:08 GMT</pubDate></item><item><title><![CDATA[Reply to Dobule Dispatch und Alternativen on Sun, 05 Jun 2011 16:06:44 GMT]]></title><description><![CDATA[<p>bzgl der kollision von flächen:</p>
<p>Es wird ein 2d spiel und bisher verwenden wir ausschließlich an den axen ausgerichtete (soll heißen nicht gedrehte) rechtecke.</p>
<p>Aber es geht hier weniger um das FINDEN von Kollisionen als um die BEHANDLUNG, also sowas wie wenn mario auf nen gegner springt, stirbt der gegner, außer wenn es sich z.B. um eine art &quot;igel&quot; handelt, dann braucht man eine spezialbehandlung</p>
<p>Danke für eure Vorschläge!<br />
Bitte melden, falls noch jemand ne Idee hat <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>
]]></description><link>https://www.c-plusplus.net/forum/post/2073666</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2073666</guid><dc:creator><![CDATA[Gast1337]]></dc:creator><pubDate>Sun, 05 Jun 2011 16:06:44 GMT</pubDate></item><item><title><![CDATA[Reply to Dobule Dispatch und Alternativen on Sun, 05 Jun 2011 16:26:54 GMT]]></title><description><![CDATA[<p>Ja, double dispatch ist wirklich hässlich zu implementieren und auch ziemlich überflüssig, wenn z.b. Wände nie mit Powerups kollidieren.</p>
<p>Wenn sich die Anzahl der Behandlungen relativ klein ist, dann schreib die 3 bis 4 if einfach hin. Wenn es viele gibt, dann mach dir so ne map &lt; pair&lt;objectTypeA, objectTypeB&gt;, event &gt;</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2073672</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2073672</guid><dc:creator><![CDATA[theearthfenomina]]></dc:creator><pubDate>Sun, 05 Jun 2011 16:26:54 GMT</pubDate></item><item><title><![CDATA[Reply to Dobule Dispatch und Alternativen on Sun, 05 Jun 2011 17:02:20 GMT]]></title><description><![CDATA[<p>Gast1337 schrieb:</p>
<blockquote>
<p>sowas wie wenn mario auf nen gegner springt, stirbt der gegner, außer wenn es sich z.B. um eine art &quot;igel&quot; handelt, dann braucht man eine spezialbehandlung</p>
</blockquote>
<p>Hm, lässt sich das dann nicht in die Spiellogik integrieren? Also statt</p>
<pre><code class="language-cpp">void mario::onCollide( object* Other ) {
    if ( igel* Igel = dynamic_cast&lt;igel*&gt;(Other) )
        this-&gt;Health -= 10;
    else
        Other-&gt;die();
}
</code></pre>
<p>lieber</p>
<pre><code class="language-cpp">void mario::onCollide( object* Other ) {
    if ( Other-&gt;hasSpikesOnBack() )
        this-&gt;Health -= Other-&gt;getSpikesStrength();
    else if ( Other-&gt;isDyingAtJumpOnBack() )
        Other-&gt;die();
}
</code></pre>
<p>?</p>
<p>Oder du abstrahierst die Kollisionen nochmal in z.B. &quot;berühren&quot;, &quot;draufspringen&quot; usw. Eine Möglichkeit dann für die Logik in Stachelsachen:</p>
<pre><code class="language-cpp">void thing_with_spiky_back::PlayerJumpsOnYourBack( player* Player ) {
    Player-&gt;suffer( this-&gt;getSpikeStrength() );
}

class igel : public thing_with_spiky_back {
    ...
};

void mario::suffer( int Strength ) {
    if ( this-&gt;IHaveArmor )
        Strength -= this-&gt;MyArmorStrength;
    if ( ! this-&gt;IHaveAStar )
        this-&gt;Health -= Strength;
    if ( this-&gt;Health &lt;= 0 )
        this-&gt;die();
}
</code></pre>
<p>Da musst du wahrscheinlich mal tabellarisch herausarbeiten, was bei welcher Aktion mit welchen Charakteren und Objekten passiert. Wenn du genug Gemeinsamkeiten findest, lässt sich das bestimmt gut zusammenfassen und in Logik gießen.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2073694</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2073694</guid><dc:creator><![CDATA[Vorschläger]]></dc:creator><pubDate>Sun, 05 Jun 2011 17:02:20 GMT</pubDate></item><item><title><![CDATA[Reply to Dobule Dispatch und Alternativen on Mon, 06 Jun 2011 10:03:00 GMT]]></title><description><![CDATA[<p>Dann gehe doch einfach noch ein wenig tiefer mit deiner Dispatchkette, dann brauchst du nur die Sonderfälle behandeln die du möchtest.<br />
Ein Aufruf sähe dann ungefähr so aus:</p>
<pre><code class="language-cpp">a.collideWith(b);
--&gt;
&lt;a&gt;
     b-&gt;WhoAreYou(this)
&lt;/a&gt;
--&gt;
&lt;b&gt;
     a-&gt;OkIam(this)
&lt;/b&gt;
--&gt;
&lt;a&gt; (in Iam)
     ...
&lt;/a&gt;
</code></pre>
<p>&quot;OkIam&quot; Sei eine Überladene Methode für die Basisklassen und für jeden Sonderfall einer konkreten Klasse.</p>
<p>So oder so ähnlich kannst du deine Viecher identifizieren, ohne in allen klassen Methoden für alle anderen anbiten zu müssen, da du ja je auch eine Überladung für die Basen hast. In den Methoden für die Basen machst du dann halt das gleiche was du jetzt auch tust.</p>
<p>cu</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2073938</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2073938</guid><dc:creator><![CDATA[Ka-Mensch]]></dc:creator><pubDate>Mon, 06 Jun 2011 10:03:00 GMT</pubDate></item><item><title><![CDATA[Reply to Dobule Dispatch und Alternativen on Mon, 06 Jun 2011 10:14:41 GMT]]></title><description><![CDATA[<p>In OkIam kennst du ja jetzt die konkrete klasse, falls dies erwünscht war und könntest dann natürlilch wieder irgendwas aus b aufrufen, dieses mal auch Methoden die es nur für diese Konkrete Klasse gibt z.B.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2073942</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2073942</guid><dc:creator><![CDATA[Ka-Mensch]]></dc:creator><pubDate>Mon, 06 Jun 2011 10:14:41 GMT</pubDate></item><item><title><![CDATA[Reply to Dobule Dispatch und Alternativen on Mon, 06 Jun 2011 10:38:47 GMT]]></title><description><![CDATA[<p>Das mit dem Igel könnte man lösen, indem die Kollision nicht von Mario, sondern vom Monster behandelt wird:</p>
<pre><code class="language-cpp">struct Monster
{
    virtual void jumped_onto(Mario&amp; m)
    {
        die();
    }
};

struct Igel : Monster
{
    virtual void jumped_onto(Mario&amp; m)
    {
        m.take_damage(10);
    }
};

struct Mario
{
    void collide_with(Monster&amp; m)
    {
        m.jumped_onto(*this);
    }
};
</code></pre>
<p>Mario ist es egal, auf welches Monster er springt. Lediglich vom Monster hängt es ab, wie es sich verhält (sterben, Schaden austeilen, beides etc.). Und schon gibt es kein Double-Dispatch mehr. Vielleicht gibt es bei anderen Fällen, wo das auftritt, ähnliche Lösungen.</p>
<p>Blöd wirds dann, wenn man neben Mario auf den Steinmenschen Igor spielen kann, der Igel zermalmt. Hier wäre es z.B. möglich, verschiedene Angriffsarten zu definieren (normaler Sprung, Sprung mit Steinhaut usw.), auf welche das Monster dann anders reagiert.<br />
Oder man macht es mit Double-Dispatch, ich bezweifle aber, dass das hier einfacher ist.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2073947</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2073947</guid><dc:creator><![CDATA[ipsec]]></dc:creator><pubDate>Mon, 06 Jun 2011 10:38:47 GMT</pubDate></item><item><title><![CDATA[Reply to Dobule Dispatch und Alternativen on Mon, 06 Jun 2011 15:43:34 GMT]]></title><description><![CDATA[<p><a class="plugin-mentions-user plugin-mentions-a" href="https://www.c-plusplus.net/forum/uid/16077">@ipsec</a>:<br />
Der Unterschied von deiner Lösung zu Double-Dispatch ist doch nur, ob <code>collide_with</code> virtual ist oder nicht.<br />
Von daher verstehe ich nicht wie eines der beiden einfacher oder weniger einfach sein soll... <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f615.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--confused_face"
      title=":confused:"
      alt="😕"
    /></p>
]]></description><link>https://www.c-plusplus.net/forum/post/2074084</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2074084</guid><dc:creator><![CDATA[hustbaer]]></dc:creator><pubDate>Mon, 06 Jun 2011 15:43:34 GMT</pubDate></item><item><title><![CDATA[Reply to Dobule Dispatch und Alternativen on Mon, 06 Jun 2011 18:08:52 GMT]]></title><description><![CDATA[<p>Die Loki-Bibliothek von Andrei Alexandrescu bietet Templates für Dynamic-Dispatch, diese werden im Buch <em>Modern C++ Design</em> entwickelt. Ist spannend zu lesen, ich hab mir auch mal was Ähnliches gebastelt <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>
]]></description><link>https://www.c-plusplus.net/forum/post/2074207</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2074207</guid><dc:creator><![CDATA[Nexus]]></dc:creator><pubDate>Mon, 06 Jun 2011 18:08:52 GMT</pubDate></item><item><title><![CDATA[Reply to Dobule Dispatch und Alternativen on Mon, 06 Jun 2011 18:43:25 GMT]]></title><description><![CDATA[<p>Danke für die zahlreichen Antworten.</p>
<p>Ich habe mich noch nicht entschieden, wie ich es langfristig löse.</p>
<p>Falls noch weitere Ideen da sind, bitte melden <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>
]]></description><link>https://www.c-plusplus.net/forum/post/2074236</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2074236</guid><dc:creator><![CDATA[Gast1337]]></dc:creator><pubDate>Mon, 06 Jun 2011 18:43:25 GMT</pubDate></item><item><title><![CDATA[Reply to Dobule Dispatch und Alternativen on Sun, 19 Jun 2011 20:48:21 GMT]]></title><description><![CDATA[<p>Hallo,</p>
<p>ich melde mich mal wieder hierzu, weil es neuigkeiten gibt.</p>
<p>Im eigentlichen Programm haben wir bisher noch nichts geändert, aber wir planen, alles neu zu machen und dann wäre es gut einen geeigneten ansatz zu verwenden.<br />
Beim neumachen soll auch unterstürzung für netzwerk mit rein, und dafür habe ich mir überlegt, dass ich die technik von virtuellen konstruktoren benutzen kann, die ich gerade bei &quot;More Effective C++&quot; gelesen habe.</p>
<p>Also sowas wie</p>
<pre><code class="language-cpp">GameObject* GameObject::CreateFromStream(istream&amp; str)
{
   int classID;
   str &gt;&gt; classID;
   //switch case / kaskadierende else ifs zum erstellen eines objekts des jeweiligen typs
   //pointer auf erstelltes objekt zurückgeben
}
</code></pre>
<p>Für dieses vorgehen brauche ich etwas wie classID's und dann dachte ich mir, wenn ich die eh schon einführe, um objekte übers netzwerk zu kriegen, dann kann ich die ids noch gleich so designen, dass ich anhand dessen auch die basisklassen rausfinden kann und dann statt double dispatch oder dynamic cast oder ähnlichem einfach je nach classID handeln kann.</p>
<p>Idee für den Aufbau der classID (soll eine riesige enum werden^^) ist dann folgendes:<br />
(GameObject ist basisklasse von allem, davon erben z.B. Enemy und Usable und davon erben wiederrum Crawler und Mushroom)<br />
GameObject -&gt; 1 //erste basisklasse<br />
Enemy -&gt; 11 //erste abgeleitete klasse der ersten basisklasse<br />
Usable -&gt; 12 //zweite abgeleitete klasse der ersten basisklasse<br />
Crawler -&gt;111 //erste konkrete klasse von ...<br />
Mushroom -&gt; 112 //zweite konkrete klasse von...<br />
Also die vorderen ziffern sind dann für die basisklassen und die letzte ist für die konkrete klasse (da brauch man dann evtl. 2 ziffern).<br />
Dann kann man durch geschickte rechnung die einzelnen stellen der zahl extrahieren und dann die basisklassen und konkrete klasse herausfinden und darauf basierend handeln.<br />
Die Zahl für gameobjekt kann man eignetlich auch sparen, weil sowieso alles davon erbt <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>Ein Nachteil ist vermutlich, dass, wenn man was zur enum hinzufügt, einiges neukompiliert werden muss...</p>
<p>Was haltet ihr davon?<br />
Hat das ganze sonst noch irgenwelchen großen Nachteile?<br />
Gibt es bessere Alternativen?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2080839</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2080839</guid><dc:creator><![CDATA[Gast1337]]></dc:creator><pubDate>Sun, 19 Jun 2011 20:48:21 GMT</pubDate></item><item><title><![CDATA[Reply to Dobule Dispatch und Alternativen on Mon, 20 Jun 2011 09:15:47 GMT]]></title><description><![CDATA[<p>Ich würde ein std::bitset verwenden. Jede Klasse erhält einen Eintrag in der erwähnten enum. Dann setzt einfach jede Klasse im Kosntruktor bitset[ID] auf true.<br />
In etwa so:</p>
<pre><code class="language-cpp">enum ClassID
{
    ...
    ANYDERIVED,
    ...
    NUMBER_OF_CLASSES
};

class Base
{
protected:
    std::bitset&lt; NUMBER_OF_CLASSES &gt; ids;
};
class AnyDerived
    : public Base
{
public:
    AnyDerived
    {
        ids[ ANYDERIVED ]=true;
    }
};
</code></pre>
<p>Danach sollte es ja sehr einfach sein, rauszufinden was in einem bestimmten Objekt alles drinsteckt.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2080964</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2080964</guid><dc:creator><![CDATA[GorbGorb]]></dc:creator><pubDate>Mon, 20 Jun 2011 09:15:47 GMT</pubDate></item><item><title><![CDATA[Reply to Dobule Dispatch und Alternativen on Mon, 20 Jun 2011 12:01:13 GMT]]></title><description><![CDATA[<p>Danke für die Antwort.<br />
Aber würde das nicht dazu führen, dass ich wenn ich mehr als 32 klassen habe der speicherplatz höher wird, weil ein integer für die interne speicherung des bitsets nicht mehr ausreicht?<br />
Übers netzwerk wil ich den transfer möglichst klein halten, also weiß ich nicht, ob das der beste weg ist.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2081065</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2081065</guid><dc:creator><![CDATA[Gast1337]]></dc:creator><pubDate>Mon, 20 Jun 2011 12:01:13 GMT</pubDate></item><item><title><![CDATA[Reply to Dobule Dispatch und Alternativen on Mon, 20 Jun 2011 14:51:30 GMT]]></title><description><![CDATA[<p>Was ist eigentlich Double Dispatching? Finde da keine wirklich verstaendliche Erklaerung...</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2081182</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2081182</guid><dc:creator><![CDATA[Frager..]]></dc:creator><pubDate>Mon, 20 Jun 2011 14:51:30 GMT</pubDate></item><item><title><![CDATA[Reply to Dobule Dispatch und Alternativen on Mon, 20 Jun 2011 19:44:01 GMT]]></title><description><![CDATA[<p>[quote=&quot;Gast1337&quot;]Danke für die Antwort.<br />
Aber würde das nicht dazu führen, dass ich wenn ich mehr als 32 klassen habe der speicherplatz höher wird, weil ein integer für die interne speicherung des bitsets nicht mehr ausreicht?<br />
Übers netzwerk wil ich den transfer möglichst klein halten, also weiß ich nicht, ob das der beste weg ist.[/quote]</p>
<p>Du hast schon Recht. Ich würde jetzt aber erst mal versuchen, das Programm fertig zu schreiben und mir erst dann Gedanken über einen int mehr oder weniger zu machen. Es ist gut möglich, dass dein Bottleneck wo ganz anders sein wird, dann wäre das hier verschwendete Zeit. Nur für den Fall würde ich dem Mechanismus, den du jetzt wählst, einen Wrapper verpassen damit du nicht viel neu schreiben müsstest.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2081353</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2081353</guid><dc:creator><![CDATA[GorbGorb]]></dc:creator><pubDate>Mon, 20 Jun 2011 19:44:01 GMT</pubDate></item><item><title><![CDATA[Reply to Dobule Dispatch und Alternativen on Sun, 26 Jun 2011 16:32:16 GMT]]></title><description><![CDATA[<p>Ich find das relativ schwierig zu erklären, was double dispatch ist.<br />
Ich versuchs mal in kurzform:<br />
Man will beim aufruf von überladenen methoden dafür sorgen, dass der laufzeittyp von beiden beteiligten objekten berücksichtigt wird.<br />
Also ruft man erst eine virtuelle methode auf dem ersten objekt auf, um den laufzeittyp des ersten objekts zu ermitteln und in dieser methode ruft man eine methode auf dem anderen objekt auf um den laufzeittyp des anderen objekts zu bestimmen.<br />
Beim zweiten aufruf übergibt man das erste objekt, dessen laufzeittyp dann bekannt ist als parameter.<br />
Vermutlich ist das so nicht verständlich^^<br />
Ansonsten wikipedia / google</p>
<p>So also ich hab mir das ganze nochmal überlegt und tendiere nun doch dazu, double dispatch zu verwenden.</p>
<p>Ich wollte das dann so machen:</p>
<pre><code class="language-cpp">class GameObject
{
    void initiateCollision(GameObject&amp; obj) = 0;
    void collideWith(Enemy&amp; enemy) = 0;
    void collideWith(Usable&amp; usable) = 0;
    void collideWith(Player&amp; player) = 0;

    void collideWith(Crocodile&amp; croc); // nicht = 0!
    void collideWith(Mushroom&amp; mushroom); //nicht = 0!
    //...
};
</code></pre>
<p>Also erstmal initiateCollision muss von jeder erbenden Klasse überschrieben werden und dadrin einfach machen</p>
<pre><code class="language-cpp">void XY::initiateCollision(GameObject&amp; obj)
{
   obj.collideWith(*this);
}
</code></pre>
<p>Die collideWith mit den Basisklassen müssen von jedem überschrieben werden (deswegen = 0) und irgendein standardverhalten für kollision mit objekten von dieser basisklasse festlegen.</p>
<p>Alle anderen (mit konkreten basisklasse) sind bei GameObject nach dem muster implementiert:</p>
<pre><code class="language-cpp">void GameObject::collideWith(Crocodile&amp; croc)
{
   collideWith(static_cast&lt;Enemy&amp;&gt;(croc));
}
</code></pre>
<p>Ich hoffe mal, dass das so funktioniert.</p>
<p>Alle abgeleiteten Klassen müssen also die methoden für die Basisklassen überschreiben, alle weiteren für konkrete Klassen sind optional und werden nur überschrieben, wenn für diese klasse eine sonderbehandlung nötig ist.<br />
Falls eine methode nicht überschrieben wird, sorgt die geerbte methode von GameObject dafür, dass die Behandlung für die Basisklasse aufgerufen wird.</p>
<p>Das problem dabei ist nur, dass wenn ich eine neue Klasse hinzufüge, ich bei GameObject eine neue Methode reintun muss und deswegn alle abgeleiteten Klassen neu kompilieren müssen...<br />
Ich hab mir überlegt, evtl. alle abgeleiteten Klassen zum pImpln um das problem zu vermindern, bin mir aber nicht sicher, ob das in diesem fall möglich/angebracht ist.<br />
Normalerweise tut man alles was zur pImpl-Klasse gehört in eine cpp-datei inkl der pImpl-Klassendefinition.<br />
Ich würde das dann so modifizieren, dass ich die pImpl-Klassendefinition in einen eigenen header tue und 2 cpp-dateien habe, eine für die richtige klasse mit weiterleitungsmethoden und eine für die pImpl-Klasse.<br />
Wenn ich dann die Basisklasse ändere, muss nur die &quot;richtige&quot; klasse die weiterleitungsfunktionen neu kompilieren und die pImpl-Klasse mit der eigentlichen logik bleibt unberührt (so zumindest habe ich mir das gedacht :-).</p>
<p>Was meint ihr?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2084352</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2084352</guid><dc:creator><![CDATA[Gast1337]]></dc:creator><pubDate>Sun, 26 Jun 2011 16:32:16 GMT</pubDate></item><item><title><![CDATA[Reply to Dobule Dispatch und Alternativen on Sun, 26 Jun 2011 17:15:56 GMT]]></title><description><![CDATA[<p>Ich finde diese Art, Double Dispatch zu implementieren, äusserst mühsam. Sie ist intrusiv und skaliert schlecht.</p>
<p>Es gibt auch andere Möglichkeiten, z.B. so wie es in der Loki-Bibliothek gemacht wird. Dann musst du nicht einmal die Klassen verändern. Das könnte dann ungefähr wie folgt aussehen, solche Klassen findest du ausser in Loki z.B. <a href="http://www.bromeon.ch/thor/v1.1/doc/classthor_1_1_double_dispatcher.html" rel="nofollow">hier</a>.</p>
<pre><code class="language-cpp">// Polymorphe Klassenhierarchie
class B {...};
class D1 : public B {...};
class D2 : public B {...};

// Überladene Funktionen (abgeleitete Klassen als Parameter!)
void Collision(D1&amp; lhs, D1&amp; rhs);
void Collision(D1&amp; lhs, D2&amp; rhs);
void Collision(D2&amp; lhs, D2&amp; rhs);

// Funktionen registrieren
DoubleDispatcher&lt;B&amp;&gt; dispatcher;
dispatcher.Register&lt;D1, D1&gt;(&amp;Collision);
dispatcher.Register&lt;D1, D2&gt;(&amp;Collision);
dispatcher.Register&lt;D2, D2&gt;(&amp;Collision);

// Aufruf
B* x = new D1;
B* y = new D2;
dispatcher.Call(*x, *y); // Collision(D1&amp; lhs, D2&amp; rhs)
delete x;
delete y;
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/2084377</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2084377</guid><dc:creator><![CDATA[Nexus]]></dc:creator><pubDate>Sun, 26 Jun 2011 17:15:56 GMT</pubDate></item><item><title><![CDATA[Reply to Dobule Dispatch und Alternativen on Sun, 26 Jun 2011 17:27:52 GMT]]></title><description><![CDATA[<p>Was meinst du hier mit skaliert schlecht?<br />
Man hat doch in jedem fall 2-3 virtuelle funktionsaufrufe, also sollte die laufzeit konstant sein.</p>
<p>Und kann ich bei dem was du vorgeschlagen hast auch Basisklassen gleich behandeln, ohne für jede abgeleitete Klasse nen register zu machen?</p>
<p>Das würde einiges an arbeit sparen.</p>
<p>sonst braucht man n*(n+1)/2 (glaube ich) funktionen, wenn man aber nur in sonderfällen ne spezialbehandlung braucht, kann man das stark reduzieren und dann wäre es gut, wenn man auch nicht n*(n+1)/2 mal registrieren muss.</p>
<p>Ich werds mir auf jeden fall mal angucken.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2084390</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2084390</guid><dc:creator><![CDATA[Gast1337]]></dc:creator><pubDate>Sun, 26 Jun 2011 17:27:52 GMT</pubDate></item><item><title><![CDATA[Reply to Dobule Dispatch und Alternativen on Sun, 26 Jun 2011 21:24:16 GMT]]></title><description><![CDATA[<p>Beim Ansatz mit der Dispatcher-Klasse musst du symmetrische Aufrufe <code>f(a,b)</code> und <code>f(b,a)</code> nur einmal registrieren, zudem musst du nicht bei jedem neuen Dispatch-Objekt sämtliche bestehenden Klassen anpassen. Das meinte ich mit &quot;skaliert besser&quot;: Du kannst an einer Stelle die Fälle erweitern. Die Laufzeit ist wahrscheinlich bei <code>DoubleDispatcher</code> etwas grösser, da zusätzlich zu den virtuellen Funktionen ein Lookup in einer Map auftritt. Sollte im Normalfall aber verkraftbar sein, gerade wenn die Funktionen selbst etwas komplexer sind.</p>
<p>Für die gemeinsame Behandlung von Klassen als Basisklasse ist mir bisher leider keine Lösung eingefallen, Alexandrescu hatte in seinem Buch diese Funktionalität ebenfalls weggelassen. Das Problem ist, dass die Dispatcher auf der Basis von <code>typeid</code> arbeiten, und in C++ gibt es keine Möglichkeit, eine Vererbungsrelation zur Laufzeit abzufragen. <code>is_base_of</code> aus den Type-Traits ist zwar gut, aber dazu müssen beide Klassen zur Kompilierzeit bekannt sein.</p>
<p>Das Ganze läuft darauf hinaus, dass man in irgendeiner Weise die Vererbungshierarchie manuell angehen muss. Wenn man Metaprogrammierung sinnvoll einsetzt, könnte man eventuell sogar nur eine Liste von Klassen angeben, und der Compiler findet dann heraus, welche wovon erbt. Ich könnte mal etwas tüfteln, denn wie du sagst, wäre eine Derived-To-Base-Konvertierung in manchen Fällen eine enorme Erleichterung.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2084515</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2084515</guid><dc:creator><![CDATA[Nexus]]></dc:creator><pubDate>Sun, 26 Jun 2011 21:24:16 GMT</pubDate></item><item><title><![CDATA[Reply to Dobule Dispatch und Alternativen on Mon, 04 Jul 2011 16:44:37 GMT]]></title><description><![CDATA[<p>Nochmal zu deiner Dispatcher-Klasse.</p>
<p>Nehmen wir an, ich habe 99 Klassen und kollisionen zwischen diesen sind alle registriert.<br />
Jetzt füge ich eine 100te Klasse ein.<br />
Jetzt muss ich wirklich 99 neue einträge in die map machen (wenn wir von symmetrie ausgehen, sonst noch mehr)?</p>
<p>Es wäre wünschenswert noch ein &quot;default-mapping&quot; zu haben, dass falls ein eintrag fehlt einfach die funktion für die basisklasse aufzurufen.<br />
Falls jemand eine Idee hat, wie das zu bewerkstelligen ist, bitte her damit <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="🙂"
    /><br />
Mit double dispatch ist das ja kein problem, aber dafür muss da alles neu kompilieren, wenn eine klasse dazukommt...</p>
<p>Beides gefällt mir nicht so recht, ich muss mich wohl für das kleiner übel entscheiden, ich bin mir nur noch nicht sicher, welches es ist <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>
]]></description><link>https://www.c-plusplus.net/forum/post/2088775</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2088775</guid><dc:creator><![CDATA[Gast1337]]></dc:creator><pubDate>Mon, 04 Jul 2011 16:44:37 GMT</pubDate></item><item><title><![CDATA[Reply to Dobule Dispatch und Alternativen on Mon, 04 Jul 2011 17:04:15 GMT]]></title><description><![CDATA[<p>Sry für Doppelpost, aber mir kommt gerade ne Idee:</p>
<p>Ich könnte das problem vll ungefähr so lösen:</p>
<pre><code class="language-cpp">//typedefs für kollisionsbehandlungsfunktionen für alle basisklassen
//ich weiß nicht ob die typedefs mit templates so gehen, aber sowas in der art muss doch irgendwie gehen, oder?
template &lt;class T&gt;
typedef void (*EnemyCollisionFunc)(T&amp; t, Enemy&amp; e);
template &lt;class T&gt;
typedef void (*PlayerCollisionFunc)(T&amp; t, Player&amp; p);
template &lt;class T&gt;
typedef void (*UsableCollisionFunc)(T&amp; t, Usable&amp; u);
//...

template&lt;class T&gt;
registerDefaultMapping(EnemyCollisionFunc&lt;T&gt; defaultEnemyHandlerFunc,
PlayerCollisionFunc&lt;T&gt; defaultPlayerHandlerFunc, UsableCollisionFunc&lt;T&gt; defaultUsableHandlerFunc)
{
   //gehe alle klassen durch und registriere eine default funktion
   //z.B.
   dispatcher.Register&lt;T, Ghost&gt;(defaultEnemyHandlerFunc);
   dispatcher.Register&lt;T, Zombie&gt;(defaultEnemyHandlerFunc);
   //..
   dispatcher.Register&lt;T, Mario&gt;(defaultPlayerHandlerFunc);
   //...
   dispatcher.Register&lt;T, Mushroom&gt;(defaultUsableHandlerFunc); 
   //...
   //später können spezialfälle durch neue einträge überschrieben werden
}
</code></pre>
<p><strong>Sollte doch funktionieren, oder?</strong></p>
<p>Das bringt mich noch zu einer anderen Frage:<br />
Wenn ich das symmetrisch registiere, liegt es ja nah, dass ich zur behandlung eine freie funktion habe und nicht 2 memberfunktionen aufrufe.<br />
Haltet ihr es für sinnvoll diese freie Kollisionsbehandlungsfunktionen dann in der klassen als friend zu deklarieren/definieren und dann in den freien funktionen die komplette logik zu machen, oder sollte ich memberfunktionen fürs kollidieren haben und dann in der freien handler funktion 2 memberfunktionen aufrufen?<br />
Nochmal mit codebeispiel:<br />
1.Variante:</p>
<pre><code class="language-cpp">//Ghost und Mario haben diese funktion als friend deklariert
void handleCollision(Ghost &amp; g, Mario &amp; m)
{
   //irgendne behandlung, z.B. sowas:
   g.changeDirection();
   m.takeDamage(1000);
   //evtl muss man aber auch auf private sachen zugreifen
   m.setAnimationLoop(Mario::HitByGhost);
}
</code></pre>
<p>2.Variante:</p>
<pre><code class="language-cpp">void handleCollision(Ghost &amp; g, Mario&amp; m)
{
   g.collideWith(m);
   m.collideWith(g);
}
</code></pre>
<p><strong>Was haltet ihr für besser?</strong></p>
]]></description><link>https://www.c-plusplus.net/forum/post/2088781</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2088781</guid><dc:creator><![CDATA[Gast1337]]></dc:creator><pubDate>Mon, 04 Jul 2011 17:04:15 GMT</pubDate></item><item><title><![CDATA[Reply to Dobule Dispatch und Alternativen on Mon, 04 Jul 2011 20:14:33 GMT]]></title><description><![CDATA[<p>Gast1337 schrieb:</p>
<blockquote>
<p>Es wäre wünschenswert noch ein &quot;default-mapping&quot; zu haben, dass falls ein eintrag fehlt einfach die funktion für die basisklasse aufzurufen.</p>
</blockquote>
<p>So eine Fallback-Funktion habe ich mir auch schon überlegt. Momentan kann man das auf Call-Seite erreichen, indem man die Exception bei Nicht-Finden fängt und dann selbst eine andere Funktion aufruft. Ist natürlich nicht so elegant.</p>
<p>Doch besonders flexibel ist der Fallback-Ansatz nicht, er kommt mir mehr wie ein verzweifelter Versuch vor, dem Derived-To-Base-Problem mindestens etwas näher zu kommen. Wenn ich eine Klassenhierarchie A -&gt; B -&gt; C (C am meisten abgeleitet) habe, nur B und der Fallback für A registriert ist und ich ein C übergebe, wird der Fallback aufgerufen, obwohl eigentlich B richtig wäre.</p>
<p>Ideal wäre wirklich, wenn man Basisfunktionen registrieren könnte, und diese automatisch aufgerufen werden, falls die abgeleitete Version nicht registriert ist. Aber ohne die ganze Klassenhierarchie nochmals manuell anzugeben scheint das nicht zu gehen, zumindest sehe ich keine Möglichkeit. Naja, vielleicht wäre das wirklich die beste Möglichkeit. Wenn jemand andere Ideen hat, nur her damit <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>Gast1337 schrieb:</p>
<blockquote>
<p><strong>Sollte doch funktionieren, oder?</strong></p>
</blockquote>
<p>Grundsätzlich wahrscheinlich schon, allerdings wird so eine Funktion <code>registerDefaultMapping</code> mühsam zu implementieren, wenn sie generisch sein soll. Dann bräuchte man wohl Typlisten.</p>
<p>Du könntest allerdings auch für alle Möglichkeiten ein Funktionsobjekt registrieren (z.B. <code>std::tr1::function</code> ), das dann intern weiterdispatcht. So kannst du während der Laufzeit die Zuordnung über einen Schalter ändern.</p>
<p>Gast1337 schrieb:</p>
<blockquote>
<p><strong>Was haltet ihr für besser?</strong></p>
</blockquote>
<p>Ich würde eine globale Funktion mit direkter Berechnung nehmen. Je nachdem, wie deine Klasse gekapselt ist, muss die Funktion nicht mal ein <code>friend</code> sein.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2088857</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2088857</guid><dc:creator><![CDATA[Nexus]]></dc:creator><pubDate>Mon, 04 Jul 2011 20:14:33 GMT</pubDate></item><item><title><![CDATA[Reply to Dobule Dispatch und Alternativen on Mon, 04 Jul 2011 21:03:21 GMT]]></title><description><![CDATA[<p>Danke für deine Hilfe.<br />
Wenn ich darauf achte, dass wirklich alles registriert wird, sollte das aber eigentlich hinauen.</p>
<p>Eine weitere sache über die ich nachdenke ist wie ich das mit der serialisierung mache.<br />
Wenn ich das selbst schreibe, würde ich eine enum machen, die für jede Klasse einen eintrag hat.<br />
wird dann ein objekt serialisiert, wird zuerst ein element der enum in den stream geschrieben, dann das eigentliche objekt.<br />
Beim Empfänger hat man dann eine map, die enum-werte auf virtuelle konstruktoren mappt (mit virtuellen konstruktoren ist sowas gemeint:</p>
<pre><code class="language-cpp">GameObject * createXY(sf::Packet &amp; packet);
</code></pre>
<p>)</p>
<p>Das problem ist wieder:<br />
Jede klasse muss zugriff auf die enum haben, damit man objekte der klasse &quot;fragen&quot; kann (virtuelle methode), welchen typ sie haben.<br />
Also müssen alle klassen neukompilieren, wenn eine neue dazukommt...<br />
Das wollte ich ja gerade vermeiden, deswegen überlege ich mir das ja auch mit deinem double dispatcher anstatt normalem double dispatching.</p>
<p>Ich habe mir boost::serialization angeguckt, aber einige sachen stören mich daran:<br />
Die Archive sind entweder textbasiert (z.B. xml), haben also ne menge overhead, oder binär, aber dann nicht portabel (endianess ist das (haupt-)problem, denk ich mal).<br />
Und zur Unterstützung für serialisierung von objekten durch basisklassenpointer:<br />
Das funktioniert damit im prinzip schon, aber auch da muss man registrieren).</p>
<p>Evtl. kann ich das aber auch selbst mithilfe von dieser &quot;registrierung&quot; hinbekommen?<br />
Ich könnte dann in einer funktion die direkt am anfang von main aufgerufen wird alle klassen registrieren und dann typeinfo auf die enum mappen zum serialisierung und die enum auf virtuelle konstruktoren mappen zum deserialisieren, oder so.</p>
<p>Ich überlege auch noch, ob es überhaupt sinnvoll ist, rücksicht auf sowas wie endianess zu nehmen, weil doch eigentlich eh fast alle computer auf denen man spiele spielen würde little endianess haben soweit ich weiß.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2088888</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2088888</guid><dc:creator><![CDATA[Gast1337]]></dc:creator><pubDate>Mon, 04 Jul 2011 21:03:21 GMT</pubDate></item></channel></rss>