<?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[Alternativen zu vielen if&#x2F;else]]></title><description><![CDATA[<p>Hallo <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 />
Ich hab in meinem Programm eine stelle bei denen ich viele Abfragen in Form von if und else tätige. Das sieht aber meiner Meinung nach übel aus und ich hab mir überlegt ob man das nicht irgendwie besser machen könnte.</p>
<p>Da ist mir dann auch eine Idee mit Hilfe von std::map gekommen. Auf der einen Seite die Abfrage als Schlüsselwort und dazu dann ein Pointer auf eine Funktion die in dem entsprechenden Fall ausgeführt werden soll.<br />
Das ist soweit ja kein Problem. Aber(!) die Funktionen haben unterschiedliche Parameter und einige davon sind Methoden von Klassen (die Sache mit &quot;Klassenname::Methode&quot; funktioniert hier anscheinend nicht).</p>
<p>Gibt es eine Möglichkeit diese map-Variable so umzuschreiben das man mehrere Typen verwenden kann? (boost::any ??? ). Ich komm jedenfalls nicht drauf. Oder eine ganz andere Möglichkeit?<br />
Ich bin noch relativ C++-Anfänger. Das soll nur zum basteln und Horizont erweitern sein... dennoch schonmal Danle!</p>
]]></description><link>https://www.c-plusplus.net/forum/topic/212677/alternativen-zu-vielen-if-else</link><generator>RSS for Node</generator><lastBuildDate>Wed, 14 Oct 2026 17:24:11 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/212677.rss" rel="self" type="application/rss+xml"/><pubDate>Fri, 09 May 2008 07:00:38 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to Alternativen zu vielen if&#x2F;else on Fri, 09 May 2008 07:00:38 GMT]]></title><description><![CDATA[<p>Hallo <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 />
Ich hab in meinem Programm eine stelle bei denen ich viele Abfragen in Form von if und else tätige. Das sieht aber meiner Meinung nach übel aus und ich hab mir überlegt ob man das nicht irgendwie besser machen könnte.</p>
<p>Da ist mir dann auch eine Idee mit Hilfe von std::map gekommen. Auf der einen Seite die Abfrage als Schlüsselwort und dazu dann ein Pointer auf eine Funktion die in dem entsprechenden Fall ausgeführt werden soll.<br />
Das ist soweit ja kein Problem. Aber(!) die Funktionen haben unterschiedliche Parameter und einige davon sind Methoden von Klassen (die Sache mit &quot;Klassenname::Methode&quot; funktioniert hier anscheinend nicht).</p>
<p>Gibt es eine Möglichkeit diese map-Variable so umzuschreiben das man mehrere Typen verwenden kann? (boost::any ??? ). Ich komm jedenfalls nicht drauf. Oder eine ganz andere Möglichkeit?<br />
Ich bin noch relativ C++-Anfänger. Das soll nur zum basteln und Horizont erweitern sein... dennoch schonmal Danle!</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1505811</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1505811</guid><dc:creator><![CDATA[JDieskau]]></dc:creator><pubDate>Fri, 09 May 2008 07:00:38 GMT</pubDate></item><item><title><![CDATA[Reply to Alternativen zu vielen if&#x2F;else on Fri, 09 May 2008 07:02:09 GMT]]></title><description><![CDATA[<p>vieleicht solltest du switch verwenden? ansonsten zeig doch mal code, damit wir nicht rumraten müssen in welchem Kontext du sprichst.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1505813</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1505813</guid><dc:creator><![CDATA[Firefighter]]></dc:creator><pubDate>Fri, 09 May 2008 07:02:09 GMT</pubDate></item><item><title><![CDATA[Reply to Alternativen zu vielen if&#x2F;else on Fri, 09 May 2008 07:24:36 GMT]]></title><description><![CDATA[<p>Die Abfragebedingung ist ein std::string. Also fällt das mit switch schonmal raus. Gedacht hab ich mir in etwa sowas hier:</p>
<pre><code>std::map&lt;std::string, bool (*)( std::string )&gt; Testmap;
Testmap [ std::string ( &quot;LoadMap&quot; ) ] = &amp;LoadMap;
</code></pre>
<p>Und der Aufruf wäre dann in etwa &quot;Testmap[ Kommando ](&quot;map.xml&quot;);&quot;. Wobei jetzt Kommando ein string ist und zum Beispiel &quot;LoadMap&quot; drin steht...</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1505837</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1505837</guid><dc:creator><![CDATA[JDieskau]]></dc:creator><pubDate>Fri, 09 May 2008 07:24:36 GMT</pubDate></item><item><title><![CDATA[Reply to Alternativen zu vielen if&#x2F;else on Fri, 09 May 2008 07:33:01 GMT]]></title><description><![CDATA[<p>JDieskau schrieb:</p>
<blockquote>
<p>Hallo <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 />
Ich hab in meinem Programm eine stelle bei denen ich viele Abfragen in Form von if und else tätige. Das sieht aber meiner Meinung nach übel aus und ich hab mir überlegt ob man das nicht irgendwie besser machen könnte.</p>
</blockquote>
<p>Die Üblichen Alternativen bei vielen if/else sind aus meiner Sicht switch, std::map sowie Vererbung/Polymorphie (oder Kombinationen dergleichen).</p>
<p>JDieskau schrieb:</p>
<blockquote>
<p>Da ist mir dann auch eine Idee mit Hilfe von std::map gekommen. Auf der einen Seite die Abfrage als Schlüsselwort und dazu dann ein Pointer auf eine Funktion die in dem entsprechenden Fall ausgeführt werden soll.<br />
Das ist soweit ja kein Problem. Aber(!) die Funktionen haben unterschiedliche Parameter und einige davon sind Methoden von Klassen (die Sache mit &quot;Klassenname::Methode&quot; funktioniert hier anscheinend nicht).</p>
</blockquote>
<p>Grundsätzlich lässt sich aber nicht alles Vereinheitlichen, und wenn unterschiedliche Parameter nötig sind ist das eigentlich ein Zeichen das diese Bereiche sich nicht ohne weiteres Kombinieren lassen (Jegliches Konstrukt wie boost:any und Variant sollte nicht die erste Wahl sein).</p>
<p>Zum Thema Funktionen und Methoden gibt es aber tatsächlich eine Möglichkeit der Vereinheitlichung. Grundsätzlich ist ein Motto: Wenn etwas nicht direkt erreichbar ist, hilft meist eine Ebene der Indirektion.</p>
<p>An einen Beispiel:</p>
<p>Nehmen wir einfach mal an wir haben ein Menü das wir möglichst generisch halten wollen. Damit das geht ist der erste Ansatz z.B. eine map in der auf der einen Seite ein interner Name, auf der anderen die dahinter liegende Funktion (im Sinne: etwas das auszuführen ist, nicht zwangsweise eine Funktion) ist.</p>
<p>Wie du ja schon selbst festgestellt hast kann es aber sein das die Funktion tatsächlich eine Methode oder etwas mit Parametern sein kann. Damit lässt sich aber nichts anfangen. Wir müssen es erst einmal Vereinheitlichen (Ich werde jetzt mal möglichkeiten des ausgrauens etc. für das Beispiel weglassen).</p>
<pre><code class="language-cpp">// Erster Versuch einer Vereinheitlichung (Alternativ auch über den ()-Operator etc.)
class MenueFunktion
{
    public:
        virtual ~MenueFunktion() {};
        virtual void Start() = 0;
};
</code></pre>
<p>Nun haben wir eine rein abstrakte Basisklasse die einfach einen Aufruf Start() besitzt, und könnten unsere Fälle nun davon ableiten. Die Standardfälle sind hierbei einfach. Die eine Klasse könnte einen Funktionszeiger enthalten, die andere könnte eine Templateklasse sein, die einmal eine Instanz (eben das benötigst du zu einer Methode außer dem Methodenzeiger) und eine entsprechende Methode aufnimmt...</p>
<p>Dann wäre es möglich, die Fälle in einer map zusammenzustellen (immer über den Zeiger auf die Basisklasse). Man könnte auch so weit gehen diese Basisklasse über Funktionen zu erweitern die bestimmen ob der Menüpunkt auszugrauen ist etc. Und die Abgeleiten Klassen könnte man mit Sonderfällen ergänzen, die z.B. die entsprechende Instanz erst zum Zeitpunkt des Aufrufes bestimmen (So etwas wie &quot;GetSelectedAddress()&quot; mit anschließenden &quot;addressObj.Edit()&quot;)...</p>
<p>Ich kann gerne noch ein Beispiel ausgestallten, habe aktuell aber nicht die Zeit. Themen wie Funktoren sind hier aber ein guter Anhaltspunkt (Ebenso boost::bind, boost::mem_fn...).</p>
<p>cu André</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1505845</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1505845</guid><dc:creator><![CDATA[asc]]></dc:creator><pubDate>Fri, 09 May 2008 07:33:01 GMT</pubDate></item><item><title><![CDATA[Reply to Alternativen zu vielen if&#x2F;else on Fri, 09 May 2008 07:58:26 GMT]]></title><description><![CDATA[<p>Wenn es ultraschnell sein soll kommst du um switch nicht herum (siehe <a href="http://www.c-plusplus.net/forum/viewtopic-var-t-is-209245-and-postdays-is-0-and-postorder-is-asc-and-start-is-0.html" rel="nofollow">hier</a>). Es lohnt sich vermutlich dann auch, die Strings irgendwie zu hashen oder gar nicht erst Strings sondern Konstanten zu verwenden (was vor allem dann möglich ist, wenn deine Vergleiche sowieso nur aus Literalen bestehen).</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1505863</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1505863</guid><dc:creator><![CDATA[.filmor]]></dc:creator><pubDate>Fri, 09 May 2008 07:58:26 GMT</pubDate></item><item><title><![CDATA[Reply to Alternativen zu vielen if&#x2F;else on Fri, 09 May 2008 08:28:15 GMT]]></title><description><![CDATA[<p>Wenn du die Funktionen nicht direkt in die Map packen kannst weil sie &quot;zu verschieden&quot; sind, kannst du statt dessen Keys in diese map packen. Ich hatte dazu mal ein Beispiel gebracht, habs grad nochmal rausgekramt und ein klein wenig erweitert:</p>
<pre><code class="language-cpp">void processString(std::string const&amp; str) {
  enum { NoKey = 0, Bla, Blubb, Bla2, Omfg };  //die integralen werte, in die die strings uebersetzt werden
  static std::map&lt;std::string, int&gt; smap; //einmalig angelegtes &quot;woerterbuch&quot;
  static struct S{ S(){  //der ctor des Objekts traegt die Werte ins &quot;woerterbuch&quot; ein
    smap[&quot;bla&quot;] = Bla;
    smap[&quot;blubb&quot;] = Blubb;
    smap[&quot;BLUBB&quot;] = Blubb;
    smap[&quot;bla2&quot;] = Bla2;
    smap[&quot;omfg&quot;] = Omfg;
  }} s;

  switch(smap[str]) {
    case NoKey: /* Default-initialisierung von int ist 0, also NoKey. Siehe unten... */
    case Bla: /*...*/
    case Blubb: /*..*/
    //...
  }
}
</code></pre>
<p>Kurze Erklärung:<br />
smap ist eine statische map, gibts also nur einmal. S ist eine lokale klasse (bzw. struct), von der es ein einziges statisches Objekt gibt. Bei der Konstruktion des Objekts werden die Werte in die Map eingetragen, das geschieht beim ersten Aufruf der Funktion.<br />
Bei jedem Durchlauf der Funktion wird operator[] der map aufgerufen mit dem übergebenen String. Wenn der String nicht vorgesehen ist, dann wird er als key neu in der map abgelegt und der neu erzeugte int ist 0. die zugehörige case-Marke ist dann &quot;NoKey&quot;, dort kommt also die Fehlerehandlung hin für falsche strings.<br />
Bei den anderen case-marken kannst du dann die jeweiligen Funktionen, Methoden usw. aufrufen und im Grunde machen was du willst.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1505889</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1505889</guid><dc:creator><![CDATA[pumuckl]]></dc:creator><pubDate>Fri, 09 May 2008 08:28:15 GMT</pubDate></item><item><title><![CDATA[Reply to Alternativen zu vielen if&#x2F;else on Fri, 09 May 2008 20:32:16 GMT]]></title><description><![CDATA[<p>Danke für eure Antworten. Werde mir das mal alles in Ruhe ansehen und rumexperimentieren. <a class="plugin-mentions-user plugin-mentions-a" href="https://www.c-plusplus.net/forum/uid/14941">@asc</a>, das muss ich langsam verdauen. So richtig verstanden hab ichs bis jetzt noch nicht. Die Erleuchtung kommt vielleicht noch wenn ich erstmal verstanden hab was dieses virtual ist <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f644.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--face_with_rolling_eyes"
      title=":rolling_eyes:"
      alt="🙄"
    /></p>
<p>Ich also erstmal Lesestoff. Danke <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/1506308</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1506308</guid><dc:creator><![CDATA[JDieskau]]></dc:creator><pubDate>Fri, 09 May 2008 20:32:16 GMT</pubDate></item><item><title><![CDATA[Reply to Alternativen zu vielen if&#x2F;else on Sat, 10 May 2008 06:05:23 GMT]]></title><description><![CDATA[<p>JDieskau schrieb:</p>
<blockquote>
<p>Die Erleuchtung kommt vielleicht noch wenn ich erstmal verstanden hab was dieses virtual ist <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f644.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--face_with_rolling_eyes"
      title=":rolling_eyes:"
      alt="🙄"
    /></p>
</blockquote>
<p>Damit solltest du dich befassen, unabhängig welche Lösung du verwendest, da virtual in der OOP nicht grade unwichtig ist, sobald es um Vererbung geht.</p>
<p>Hier ein kurzes Beispiel was ich anschließend erkläre:</p>
<pre><code class="language-cpp">#include &lt;iostream&gt;
#include &lt;vector&gt;
#include &lt;boost/shared_ptr.hpp&gt;

class Base
{
  public:
    // Bei Basisklasse sollte in der Regel Destruktor immer virtuell sein
    virtual ~Base() {}
    // Dies ist eine rein virtuelle Funktion, komme mit der Erklärung später
    virtual void foo() = 0;
};

class A : public Base
{
  public:
    void foo()
    {
      std::cout &lt;&lt; &quot;A::foo()\n&quot;;
    }
};

class B : public Base
{
  public:
    void foo()
    {
      std::cout &lt;&lt; &quot;B::foo()\n&quot;;
    }
};

int main()
{
  std::vector&lt;boost::shared_ptr&lt;Base&gt; &gt; liste;
  liste.push_back(boost::shared_ptr&lt;Base&gt;(new A()));
  liste.push_back(boost::shared_ptr&lt;Base&gt;(new B()));
  liste.push_back(boost::shared_ptr&lt;Base&gt;(new B()));
  liste.push_back(boost::shared_ptr&lt;Base&gt;(new A()));
  for(std::vector&lt;boost::shared_ptr&lt;Base&gt; &gt;::const_iterator pos = liste.begin(), end = liste.end();
    pos != end; ++pos)
  {
    (*pos)-&gt;foo();
  }

  int a;
  std::cin &gt;&gt; a;
}
</code></pre>
<p>Ein kleines Vorwort, da du vermutlich boost::shared_ptr nicht kennst: Dies ist ein sogenannter Smartpointer, der sich darum kümmert das am Schluß delete aufgerufen wird (er macht noch mehr, aber für das Beispiel reicht es zu wissen das es mir nur darum geht das ich nicht anschließend die Elemente händisch löschen muss). Das Beispiel hätte auch mit einen std::vector&lt;Base*&gt; geklappt, nur müsste man dann wie gesagt an das delete denken...</p>
<p>Nun aber zum Eigentlichen: Ich habe eine Basisklasse Base und zwei davon abgeleitete Klassen A und B. Base besitzt als rein virtuelle Methode &quot;void foo()&quot;, die von den abgeleiteten Klassen überschrieben wird. Zugreifen tue ich über Zeiger auf die Basisklasse, sprich der konkrete Typ ist zum Zeitpunkt des aufrufend von foo() dem Anwender unbekannt. Nun kommt der Mechanismus zum tragen der mit virtual zu tun hat. virtual sorgt davor das die &quot;richtige&quot; Methode aufgerufen wird (Um genau zu sein: die Methode im Vererbungsbaum die am nächsten am konkreten Objekt ist, dies ist wichtig falls es über mehr als 2 Ebenen geht).</p>
<p>Nun gibt es zwei möglichkeiten virtual zu verwenden:<br />
a) Virtuelle Methode:<br />
Diese Methode hat eine Definition, sofern in der abgeleiteten Klasse diese Methode nicht überschrieben wird, wird diese ausgeführt (Sprich: dies ist dann sinnvoll wenn du weist wie der Regelfall abzuarbeiten ist, aber auch eine andere Variante zulassen möchtest).<br />
b) Rein Virtuelle Methode:<br />
Diese Methode hat nur eine Deklaration (mit einem = 0 am Ende). Von einer Klasse die rein virtuelle Methoden bestitzen, können keine Instanzen gebildet werden (das gleiche gilt für abgeleitete Klassen, die diese Methoden nicht überschreiben). Dies ist dann sinnvoll wenn die Klasse entweder als reine Schnittstelle dient (entspricht dem Interface in Java) oder wenn es nicht möglich wäre hierfür eine sinnvolle Behandlung zu schreiben, ohne das wissen der abgeleiteten Klassen zu haben.<br />
Ein Sonderfall: Man kann auch den Destruktor rein virtuell deklarieren, muss diesen aber dennoch definieren. Dies ist dann sinnvoll, wenn die Klasse als solche nicht instanzierbar sein soll, aber es keine andere rein virtuelle Methode gibt.</p>
<p>cu André</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1506376</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1506376</guid><dc:creator><![CDATA[asc]]></dc:creator><pubDate>Sat, 10 May 2008 06:05:23 GMT</pubDate></item></channel></rss>