<?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[(E)numerierte Klassen?]]></title><description><![CDATA[<p>Hi,</p>
<p>wie der Titel schon sagt, suche ich eine möglichkeit, Klassen durchzunumerieren. Ich meine also nicht ein Array von Objekten, sondern eine Art Array von Klassen - oder eher eine durchnumerierte Sammlung.</p>
<p>Wozu? Ich habe einen Netzwerk-Code, bei dem das erste byte darüber entscheidet, um welchen Paket-Type es sich handelt, und dann den stream in die jeweilige Klasse einliest.</p>
<pre><code class="language-cpp">class Pack1 : public PacketBase ...
class Pack2 : public PacketBase ...

PacketBase* pb;
switch(byte1)
{
 case PACK_TYPE_1:
  pb = new Pack1;
 break;
 case PACK_TYPE_2:
  pb = new Pack2;
 break;
 //...
}
</code></pre>
<p>Diese switch-Schleife verbraucht viel Platz und macht mir auch sonst einen fehleranfälligen Eindruck. Viel einfacher ginge es doch so:</p>
<pre><code class="language-cpp">class Pack[PACK_TYPE_1] : public PacketBase ...
class Pack[PACK_TYPE_2] : public PacketBase ...

PacketBase* pb = new Pack[byte1];
</code></pre>
<p>Mir ist klar, dass das mit Arrays aus verschiedenen Gründen überhaupt nicht ginge. Vielleicht kann man aber meine Klassen mithilfe von Templates durchnumerieren oder gibt es eine andere sinnvolle Möglichkeit? Kann man das switch irgendwie sinnvoll umgehen?</p>
<p>Mfg,<br />
voidpointer</p>
]]></description><link>https://www.c-plusplus.net/forum/topic/223629/e-numerierte-klassen</link><generator>RSS for Node</generator><lastBuildDate>Sat, 03 Oct 2026 19:19:00 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/223629.rss" rel="self" type="application/rss+xml"/><pubDate>Sun, 28 Sep 2008 21:07:24 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to (E)numerierte Klassen? on Sun, 28 Sep 2008 21:09:36 GMT]]></title><description><![CDATA[<p>Hi,</p>
<p>wie der Titel schon sagt, suche ich eine möglichkeit, Klassen durchzunumerieren. Ich meine also nicht ein Array von Objekten, sondern eine Art Array von Klassen - oder eher eine durchnumerierte Sammlung.</p>
<p>Wozu? Ich habe einen Netzwerk-Code, bei dem das erste byte darüber entscheidet, um welchen Paket-Type es sich handelt, und dann den stream in die jeweilige Klasse einliest.</p>
<pre><code class="language-cpp">class Pack1 : public PacketBase ...
class Pack2 : public PacketBase ...

PacketBase* pb;
switch(byte1)
{
 case PACK_TYPE_1:
  pb = new Pack1;
 break;
 case PACK_TYPE_2:
  pb = new Pack2;
 break;
 //...
}
</code></pre>
<p>Diese switch-Schleife verbraucht viel Platz und macht mir auch sonst einen fehleranfälligen Eindruck. Viel einfacher ginge es doch so:</p>
<pre><code class="language-cpp">class Pack[PACK_TYPE_1] : public PacketBase ...
class Pack[PACK_TYPE_2] : public PacketBase ...

PacketBase* pb = new Pack[byte1];
</code></pre>
<p>Mir ist klar, dass das mit Arrays aus verschiedenen Gründen überhaupt nicht ginge. Vielleicht kann man aber meine Klassen mithilfe von Templates durchnumerieren oder gibt es eine andere sinnvolle Möglichkeit? Kann man das switch irgendwie sinnvoll umgehen?</p>
<p>Mfg,<br />
voidpointer</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1589905</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1589905</guid><dc:creator><![CDATA[voidpointer]]></dc:creator><pubDate>Sun, 28 Sep 2008 21:09:36 GMT</pubDate></item><item><title><![CDATA[Reply to (E)numerierte Klassen? on Sun, 28 Sep 2008 22:15:07 GMT]]></title><description><![CDATA[<p>man kann per präprozessor direktiven arbeiten</p>
<p>der befehl ## hängt ja irgendwie den quellcode zusammen<br />
<a href="http://de.wikibooks.org/wiki/C%2B%2B-Programmierung:_Weitere_Grundelemente:_Vorarbeiter_des_Compilers#.23" rel="nofollow">http://de.wikibooks.org/wiki/C%2B%2B-Programmierung:_Weitere_Grundelemente:_Vorarbeiter_des_Compilers#.23</a></p>
]]></description><link>https://www.c-plusplus.net/forum/post/1589928</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1589928</guid><dc:creator><![CDATA[Skym0sh0]]></dc:creator><pubDate>Sun, 28 Sep 2008 22:15:07 GMT</pubDate></item><item><title><![CDATA[Reply to (E)numerierte Klassen? on Mon, 29 Sep 2008 05:18:12 GMT]]></title><description><![CDATA[<p>Spontan hätte ich jetzt gesagt mit template &lt;int i&gt; class Pack - aber das geht in deinem Fall leider nicht, weil das Templateargument zur Compilezeit feststehen muss.<br />
Um die eine oder andere Art Fallunterscheidung kommst du wohl nicht drum herum. Du kannst natürlich das Ganze in einer Funktion kapseln:</p>
<pre><code class="language-cpp">PacketBase* createPacket(int n)
{
  switch (n)
  case 1: return new Packet1;
  case 2: return new Packet2;
  default: /* FEHLER */
}
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/1590003</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1590003</guid><dc:creator><![CDATA[pumuckl]]></dc:creator><pubDate>Mon, 29 Sep 2008 05:18:12 GMT</pubDate></item><item><title><![CDATA[Reply to (E)numerierte Klassen? on Mon, 29 Sep 2008 07:01:23 GMT]]></title><description><![CDATA[<pre><code class="language-cpp">#include &lt;map&gt;

class PacketBase
{
};

class Packet1 : public PacketBase
{
};

class Packet2 : public PacketBase
{
};

typedef PacketBase* (*PacketCreater)();

class Creater
{
   public:
      PacketBase* Create(int index) const;
      void Register(int index, PacketCreater func);
   private:
      std::map&lt;int, PacketCreater&gt; creaters;
};

PacketBase* Creater::Create(int index) const
{
   std::map&lt;int, PacketCreater&gt;::const_iterator it = creaters.find(index);
   if(it != creaters.end())
   {
      return (it-&gt;second)();
   }
   else
   {
      return 0;
   }
}

void Creater::Register(int index, PacketCreater func)
{
   creaters[index] = func;
}

template&lt;typename T&gt;
PacketBase* CreateNew()
{
   return new T;
}

int main()
{
   Creater myCreater;
   myCreater.Register(1, CreateNew&lt;Packet1&gt;);
   myCreater.Register(2, CreateNew&lt;Packet2&gt;);
   //...
}
</code></pre>
<p>Du könntest eine kleine Factory (so ähnlich wie oben) entwerfen... Ist aber in deinem Fall vielleicht ein wenig übertrieben. Aber eine bessere Lösung als das und was bisher gesagt wurde fällt mir auch nicht ein <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f61e.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--disappointed_face"
      title=":("
      alt="😞"
    /></p>
<p>Felix</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1590041</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1590041</guid><dc:creator><![CDATA[Phoemuex]]></dc:creator><pubDate>Mon, 29 Sep 2008 07:01:23 GMT</pubDate></item><item><title><![CDATA[Reply to (E)numerierte Klassen? on Mon, 29 Sep 2008 06:48:16 GMT]]></title><description><![CDATA[<p>Tjaaaa, da sind wir insgesamt wohl wieder beim klassischen Thema &quot;C++ ist eine Sprache mit statischer Typisierung&quot; angekommen - und deswegen &quot;geht das&quot; nicht wirklich (von Grund auf erst zur Laufzeit bestimmen, was man denn mit den reinkommenden Daten machen möchte).</p>
<p>:p</p>
<p>Ich würde auch mit Phoemux' Ansatz loslegen ... allerdings kann man da vielleicht noch ein wenig sparen, indem man aus Paket1-n ein template&lt;int&gt; macht; aber das bringt nur etwas, wenn man genügend Überschneidungen zwischen den einzelnen Pakt-Typen hat.</p>
<p>Gruß,</p>
<p>Simon2.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1590048</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1590048</guid><dc:creator><![CDATA[Simon2]]></dc:creator><pubDate>Mon, 29 Sep 2008 06:48:16 GMT</pubDate></item><item><title><![CDATA[Reply to (E)numerierte Klassen? on Mon, 29 Sep 2008 12:43:03 GMT]]></title><description><![CDATA[<p>Das ist doch ein klasse Fall für <a href="http://en.wikipedia.org/wiki/Prototype_pattern" rel="nofollow">Prototypes</a>. Da man die Typen zur Laufzeit nicht bekommt, benutzt man halt nicht konventionelle OOP sondern Prototyp-OOP: Die verschiedenen Klassen werden in einem Array untergebracht, das so aussieht:</p>
<pre><code class="language-cpp">vector&lt;PacketBase*&gt; prototypes;
prototypes.push_back(new Packet1());
prototypes.push_back(new Packet2());
// …
</code></pre>
<p>Statt einer Instanzierung wird dann dieser Prototyp geklont:</p>
<pre><code class="language-cpp">PacketBase* pb = prototypes[byte1]-&gt;clone();
</code></pre>
<p>… die `clone`-Routine muss dann natürlich entsprechend implementiert werden, sollte aber nicht allzu schwer sein.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1590236</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1590236</guid><dc:creator><![CDATA[Konrad Rudolph]]></dc:creator><pubDate>Mon, 29 Sep 2008 12:43:03 GMT</pubDate></item><item><title><![CDATA[Reply to (E)numerierte Klassen? on Mon, 29 Sep 2008 13:57:58 GMT]]></title><description><![CDATA[<p>hmm grobe Idee wie man das mit den Prototypes usw. verallgemeinern könnte als templategschichte mit dem index als template-Parameter:<br />
(nur mal so hingeferkelt)</p>
<pre><code class="language-cpp">template &lt;class Base&gt;
class PrototypeFactory
{
public:
  virtual ~PrototypeFactory() = 0
  {
    for (std::map&lt;int,Base*&gt;::iterator pos = ptmap.begin(); pos != ptmap.end(); ++pos)
    {
      delete pos-&gt;second;
    }
  }

  static Base* create(int index)
  {
    std::map&lt;int,Base*&gt;::iterator pos = ptmap.find(index);
    if (pos == ptmap.end() ) 
    {
      throw std::out_of_range();
    }
    return pos-&gt;second-&gt;clone();
  }

  virtual Base* clone() = 0; //Alle abgeleiteten Klassen müssen Klonbar sein...

  template &lt;class Derived, int Index&gt;
  friend class RegisterPrototype&lt;Base, Derived, Index&gt;::Init
private:
  static std::map&lt;int, Base*&gt; ptmap;
};

template &lt;class Base, class Derived, int N&gt;
class RegisterPrototype : public Base
{
public:
  friend class PrototypeFactory&lt;Base&gt;; //weiss nicht ob das noetig ist damit PF&lt;Base&gt; Init als friend deklarieren kann

  static Base* create() {return create(N);}

private:
  class Init
  {
    Init()
    {
      PrototypeFactory&lt;Base&gt;::ptmap[N] = new Derived();
    }
  }
  const static Init i;
};
template &lt;class Base, class Derived, int N&gt;
const RegisterPrototype&lt;Base,Derived,N&gt;::Init i;  //Definition des statischen Members
</code></pre>
<p>Benutzung:</p>
<pre><code class="language-cpp">class PacketBase : public PrototypeFactory&lt;PacketBase&gt;
{ /*...*/ };

template&lt;int N&gt;
class Packet : public RegisterPrototype&lt;PacketBase, Packet&lt;N&gt;, N&gt;
{ /*...*/ };
</code></pre>
<p>Eine Instantiierung (z.B. Packet&lt;13&gt;) erbt indirekt von PacketBase, durch die Initialisierung des statischen Members von RegisterPrototype&lt;PacketBase,Packet&lt;13&gt;,13&gt; wird automatisch ein Objekt von Packet&lt;13&gt; in der Map der Prototype-Factory abgelegt.</p>
<p>Ich habs ehrlich gesagt nicht ausprobiert, vielleicht hat ja jemand die Muße - oder kann mir gleich sagen warums nicht klappen kann.<br />
Evtl. müsste die map nach Singleton-Muster in eine mapinstance()-Methode gepackt werden um Problemen bei der Initialisierungsreihenfolge aus dem Weg zu gehn.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1590282</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1590282</guid><dc:creator><![CDATA[pumuckl]]></dc:creator><pubDate>Mon, 29 Sep 2008 13:57:58 GMT</pubDate></item><item><title><![CDATA[Reply to (E)numerierte Klassen? on Mon, 29 Sep 2008 19:56:11 GMT]]></title><description><![CDATA[<p>Vielen Dank, nun habe ich mal einen kleinen Einblick bekommen. Das mit der map scheint mir eine sinnvolle Idee (hat nur den Nachteil, dass man erst mal 100 Pakete initialisieren muss <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f61e.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--disappointed_face"
      title=":("
      alt="😞"
    /> - aber trotzdem gut)</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1590527</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1590527</guid><dc:creator><![CDATA[voidpointer]]></dc:creator><pubDate>Mon, 29 Sep 2008 19:56:11 GMT</pubDate></item></channel></rss>