<?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[Funktionsaufrufe]]></title><description><![CDATA[<p>Hallo!<br />
habe folgendes Problem:<br />
baue einen Parser für ... etwa 200 Funktionen.<br />
Wenn ich den Funktionsnamen fertig geparst habe, möchte ich aber nicht 199x<br />
if(geparst == &quot;Funktionsstring&quot;)<br />
Funktionsaufruf();</p>
<p>elseif.....<br />
.<br />
In C habe ich das elegant mit functionpointer gelöst. Also Buffer von Strukturen, die folgendermaßen aussahen:<br />
struct{<br />
char* name;<br />
void*(ptFkt)(void);<br />
}MyStruct;<br />
MyStruct str[199]; //dem Sinn nach</p>
<p>Dann konnte einfach der Buffer nach den einzelnen strings durchgesucht werden und einfach über den Functionpointer die korrekte Funktion angesprungen werden.</p>
<p>Wie kann ich das am einfachsten in C++ erreichen?</p>
<p>Bitte um Ideen!</p>
<p>Danke T.O.</p>
]]></description><link>https://www.c-plusplus.net/forum/topic/135241/funktionsaufrufe</link><generator>RSS for Node</generator><lastBuildDate>Sat, 29 Aug 2026 00:09:30 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/135241.rss" rel="self" type="application/rss+xml"/><pubDate>Tue, 31 Jan 2006 19:13:00 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to Funktionsaufrufe on Tue, 31 Jan 2006 19:13:00 GMT]]></title><description><![CDATA[<p>Hallo!<br />
habe folgendes Problem:<br />
baue einen Parser für ... etwa 200 Funktionen.<br />
Wenn ich den Funktionsnamen fertig geparst habe, möchte ich aber nicht 199x<br />
if(geparst == &quot;Funktionsstring&quot;)<br />
Funktionsaufruf();</p>
<p>elseif.....<br />
.<br />
In C habe ich das elegant mit functionpointer gelöst. Also Buffer von Strukturen, die folgendermaßen aussahen:<br />
struct{<br />
char* name;<br />
void*(ptFkt)(void);<br />
}MyStruct;<br />
MyStruct str[199]; //dem Sinn nach</p>
<p>Dann konnte einfach der Buffer nach den einzelnen strings durchgesucht werden und einfach über den Functionpointer die korrekte Funktion angesprungen werden.</p>
<p>Wie kann ich das am einfachsten in C++ erreichen?</p>
<p>Bitte um Ideen!</p>
<p>Danke T.O.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/982428</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/982428</guid><dc:creator><![CDATA[Theresa]]></dc:creator><pubDate>Tue, 31 Jan 2006 19:13:00 GMT</pubDate></item><item><title><![CDATA[Reply to Funktionsaufrufe on Tue, 31 Jan 2006 21:15:14 GMT]]></title><description><![CDATA[<p>Vielleicht eine std::map?</p>
<pre><code class="language-cpp">#include &lt;map&gt;
#include &lt;string&gt;

typedef void(*Fn)();
typedef std::map&lt;std::string, Fn&gt; FnMap;

//...

FnMap myMap;

//...

void initMap() {

  myMap[&quot;func 1&quot;] = func1;
  myMap[&quot;func 2&quot;] = func2;

  // ...undsoweiter...

}

void callFunction(const std::string &amp;name) {

  FnMap::iterator iter = myMap.find(name);
  if(iter != myMap.end()) (*iter-&gt;second)();
}
</code></pre>
<p>Natürlich basiert das auf einer globalen Map mit globalen Funktionen. Natürlich(?) ist der Code nicht getestet. Aber es geht ja um's Prinzip.</p>
<p>Stefan.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/982565</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/982565</guid><dc:creator><![CDATA[DStefan]]></dc:creator><pubDate>Tue, 31 Jan 2006 21:15:14 GMT</pubDate></item><item><title><![CDATA[Reply to Funktionsaufrufe on Wed, 01 Feb 2006 07:44:47 GMT]]></title><description><![CDATA[<p>Danke! Werd gleich mal map untersuchen!!<br />
<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/982709</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/982709</guid><dc:creator><![CDATA[Theresa]]></dc:creator><pubDate>Wed, 01 Feb 2006 07:44:47 GMT</pubDate></item><item><title><![CDATA[Reply to Funktionsaufrufe on Wed, 01 Feb 2006 09:02:54 GMT]]></title><description><![CDATA[<p>Der Ansatz ist super.<br />
Mein Problem: Ich habe Kommandoklassen!<br />
Also:</p>
<pre><code class="language-cpp">Class A
{
  string eins;
  string zwei;
  //usw

  funktion_eins();
  funktion_zwei();
};

Class B
{
  string drei;
  string vier;
  //usw
  funktion_drei();
  funktion_vier();
};
</code></pre>
<p>so auf die Art eben.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/982783</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/982783</guid><dc:creator><![CDATA[Theresa]]></dc:creator><pubDate>Wed, 01 Feb 2006 09:02:54 GMT</pubDate></item><item><title><![CDATA[Reply to Funktionsaufrufe on Wed, 01 Feb 2006 09:58:47 GMT]]></title><description><![CDATA[<p>Da wird es etwas schwieriger (aber nur unwesentlich), weil du zu einem aufruf noch das Objekt benötigst. Du könntest eventuell alle Kommandoklassen von einer Basisklasse ableiten und dann die Kombination Objekt/Methode speichern:</p>
<pre><code class="language-cpp">class Command
{
public:
  typedef void Command::(*Command_Fun)();
}

class A:public Command
{
public:
  void function1();
  void function2();
  ...
};

class B:public Command
{
  ...
};

map&lt;string,pair&lt;Command*,Command::Command_Fun&gt; &gt; FnMap;
FnMap[&quot;A1&quot;]=make_pair(new A,A::function1);
...

FnMap::iterator iter = myMap.find(name);
if(iter != myMap.end()) (iter-&gt;second-&gt;first)-&gt;(*iter-&gt;second-&gt;second)();
</code></pre>
<p>(genauso ungetestet wie DStefan's Code)</p>
<p>oder du verpasst jeder Kommandoklasse eine virtuelle Methode run(), die du aufrufen kannst:</p>
<pre><code class="language-cpp">map&lt;string,Command&gt; myMap;
...
if((pos=myMap.find(name))!=myMap.end()) pos-&gt;second-&gt;run()
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/982831</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/982831</guid><dc:creator><![CDATA[CStoll (off)]]></dc:creator><pubDate>Wed, 01 Feb 2006 09:58:47 GMT</pubDate></item><item><title><![CDATA[Reply to Funktionsaufrufe on Wed, 01 Feb 2006 11:46:17 GMT]]></title><description><![CDATA[<p>Hallo Theresa,</p>
<p>also wenn du dein Design schon auf Kommandoklassen aufbaust, würde ich es &quot;sauberer&quot; finden, wenn tatsächlich pro Kommando nur eine Klasse zuständig wäre. Natürlich funktionieren alle bisher geposteten Vorschläge, trotzdem möchte ich noch etwas vorstellen, das vielleicht noch besser ist. Nimm eine Klasse Dispatcher, bei der sich Unterklassen einer abstrakten Klasse Command anmelden können:</p>
<pre><code class="language-cpp">class Command {

public:
  virtual ~Command() { }
  virtual std::string name() const { return _name; }
  virtual void run() = 0;

protected:
  Command(const std::string &amp;name)
    : _name(name)
    {
    }

private:
  std::string _name;
};

class Dispatcher {

  typedef std::map&lt;std::string, Command *&gt; MyMap;

public:
  static Dispatcher &amp;instance() {
    static Dispatcher inst;
    return inst;
  }
  void register(Command *cmd) {
    _myMap[cmd-&gt;name()] = cmd;
  }
  void runCommand(const std::string &amp;name) {
    _myMap[name]-&gt;run();
  }
private:
  // Keine Konstruktion/Destruktion von außen:
  Dispatcher() {
  }
  ~Dispatcher() {
  }

  MyMap _myMap;
};
</code></pre>
<p>Wie du siehst, ist die Klasse ein Singleton. Der Einfachheit halber habe ich alle Funktionen inline gemacht, was zumindest im Falle von instance() vielleicht nicht so bleiben sollte. Ebenfalls der Einfachheit halber unterbleibt im Beispiel jede Fehlerbehandlung.</p>
<p>Mit dieser Lösung schlägst du gleich mehrere Fliegen mit einer Klappe:</p>
<ul>
<li>Es braucht im Programm keine zentrale Stelle mehr geben, an der die Kommandoliste gepflegt wird. Vielmehr kann man jedes Kommando für sich veranlassen, sich beim Dispatcher anzumelden.</li>
<li>Der Dispatcher ist unabhängig von &quot;realen&quot; Kommandos, hängt also insbesondere nicht von den Unterklassen von Command ab.</li>
<li>Um ein Kommando abzusetzen, braucht man keine Kenntnis von den realen Kommandos, sondern nur den Namen. Auch hier werden also Abhängigkeiten vermieden. Außerdem kannst du nun, falls notwendig, viele Stellen im Programm haben, von denen aus Kommandos abgesetzt werden. Man braucht ja nur Dispatcher::instance() aufzurufen, um das Singleton-Objekt zu erhalten.</li>
</ul>
<p>Der Vollständigkeit halber, hier ein konkretes Kommando:</p>
<pre><code class="language-cpp">// In filecmd.h

class CmdFileOpen: public Command {

public:
  virtual void run();

protected:
  CmdFileOpen(const std::string &amp;name);

private:
  CmdFileOpen();

  static CmdFileOpen _fileOpen;
};

// In filecmd.cpp

CmdFileOpen CmdFileOpen::_fileOpen;

CmdFileOpen::CmdFileOpen()
  : Command(&quot;FileOpen&quot;)
{
  Dispatcher::instance().register(this);
}

CmdFileOpen::CmdFileOpen(const std::string &amp;name)
  : Command(name)
{
  // Vielleicht nicht hier, sondern in der Unterklasse registrieren (s. Text)?
  Dispatcher::instance().register(this);
}

void CmdFileOpen::run(){

  // Was auch immer....
}
</code></pre>
<p>Hier registriert sich also CmdFileOpen im Konstruktor beim Start des Programms selbst. Dadurch, dass der Ctor private ist, kann man auch nicht mehrere Kommandos registrieren. Der protected Ctor sorgt dafür, dass eine Kommando-Hierarchie möglich ist. Vielleicht ist es übrigens nicht angebracht, dass dieser Ctor bereits eine Registrierung durchführt - immerhin ist die Unterklasse zu diesem Zeitpunkt nicht voll initialisiert.</p>
<p>Der Nachteil dieser Implementierung ist, dass man auf keinen Fall während der Initialisierung/Deinitialisierung des Programms (also vor oder nach main()) Kommandos absetzen oder sonstwie auf den Dispatcher zugreifen darf. Da die Reihenfolge, in der globale Objekte initialisiert und abgebaut werden, nicht definiert ist, kann das zu schwer reproduzierbaren Fehlern führen. Aus demselben Grund dürfen sich Command-Objekte auch nicht im Destruktor beim Dispatcher abmelden.</p>
<p>Ich finde dieses Entwurfsmuster sehr nützlich und habe es bereits mehrfach erfolgreich eingesetzt. Die oben genannten Nachteile habe ich eigentlich nie als störend empfunden.</p>
<p>Stefan.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/982890</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/982890</guid><dc:creator><![CDATA[DStefan]]></dc:creator><pubDate>Wed, 01 Feb 2006 11:46:17 GMT</pubDate></item><item><title><![CDATA[Reply to Funktionsaufrufe on Wed, 01 Feb 2006 12:31:42 GMT]]></title><description><![CDATA[<p>Den Aufruf von Dispatcher::register könnte man auch noch in den Constructor der Basisklasse ablegen, dann brauchts nicht pro Ableitung geschrieben zu werden <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/982928</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/982928</guid><dc:creator><![CDATA[LordJaxom]]></dc:creator><pubDate>Wed, 01 Feb 2006 12:31:42 GMT</pubDate></item><item><title><![CDATA[Reply to Funktionsaufrufe on Wed, 01 Feb 2006 12:36:14 GMT]]></title><description><![CDATA[<p>Vielen Dank für die Vorschläge!<br />
Ich habe jedoch ein kleines Verständnisproblemlä!</p>
<pre><code class="language-cpp">map&lt;string,pair&lt;Command*,Command::Command_Fun&gt; &gt; FnMap;
FnMap[&quot;A1&quot;]=make_pair(new A,A::function1);
</code></pre>
<p>Was genau passiert hier im pair&lt;..,..&gt;. Was passiert da mit Basisklasse und abgeleiteter? Als Command* und new A. Hier wird doch ein Objekt der Klasse A auf dem Heap mit Pointer Command* erzeugt. Irgendwie wird mir der Nutzen davon nicht ganz klar...<br />
Gruss<br />
Theresa</p>
]]></description><link>https://www.c-plusplus.net/forum/post/982938</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/982938</guid><dc:creator><![CDATA[Theresa]]></dc:creator><pubDate>Wed, 01 Feb 2006 12:36:14 GMT</pubDate></item><item><title><![CDATA[Reply to Funktionsaufrufe on Wed, 01 Feb 2006 12:44:21 GMT]]></title><description><![CDATA[<p>ein &quot;Command*&quot; kann auf ein beliebiges von Command abgeleitetes Objekt zeigen, also auch auf ein A - und da du für Aufrufe von A::xyz() ein A-Objekt benötigst, mußt du da ein passendes erzeugen. (wobei - so sicher bin ich mir auch nicht, daß das wirklich funktionieren kann)</p>
]]></description><link>https://www.c-plusplus.net/forum/post/982948</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/982948</guid><dc:creator><![CDATA[CStoll (off)]]></dc:creator><pubDate>Wed, 01 Feb 2006 12:44:21 GMT</pubDate></item><item><title><![CDATA[Reply to Funktionsaufrufe on Wed, 01 Feb 2006 13:07:12 GMT]]></title><description><![CDATA[<p>Irgendwie kommt mir die Reihenfolge etwas komisch vor.</p>
<p>Basisklasse -&gt; abgeleitete.</p>
<p>Mache Pointer von Basisklasse und wandle diesen in alle möglichen abgeleiteten.<br />
Wäre nicht der umgekehrte Weg sinnvoll?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/982974</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/982974</guid><dc:creator><![CDATA[Theresa]]></dc:creator><pubDate>Wed, 01 Feb 2006 13:07:12 GMT</pubDate></item><item><title><![CDATA[Reply to Funktionsaufrufe on Wed, 01 Feb 2006 13:08:47 GMT]]></title><description><![CDATA[<p>Ist doch auch der umgekehrte Weg: Erzeuge Pointer einer abgeleiteten Klasse und reiche ihn als Basisklassen-Pointer weiter.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/982978</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/982978</guid><dc:creator><![CDATA[CStoll (off)]]></dc:creator><pubDate>Wed, 01 Feb 2006 13:08:47 GMT</pubDate></item><item><title><![CDATA[Reply to Funktionsaufrufe on Wed, 01 Feb 2006 17:40:00 GMT]]></title><description><![CDATA[<p>LordJaxom schrieb:</p>
<blockquote>
<p>Den Aufruf von Dispatcher::register könnte man auch noch in den Constructor der Basisklasse ablegen, dann brauchts nicht pro Ableitung geschrieben zu werden <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>
</blockquote>
<p>Klar, könnte man. Aber wenn man so vorgeht, hat das Nachteile:<br />
Erstens ist zum Zeitpunkt der Registrierung das Objekt der abgeleiteten Klasse nicht vollständig initialisiert. Das habe ich in meinem Beitrag schon (an anderer Stelle) erwähnt. Solange der Pointer beim Registrieren ohnehin nur gespeichert wird, ist das natürlich kein Problem.<br />
Zweitens verhindert damit die Basisklasse, dass man Unterklassen erzeugt, die nicht gleich beim Erzeugen registriert werden. Im Beispiel wären das vielleicht Kommandos, die nur temporär vorhanden sind, also etwa je nach Status des Programms.</p>
<p>Das ist also eine Design-Frage, denn beide Nachteile müssen in einem konkreten Programm ja nicht stören.</p>
<p>Stefan.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/983327</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/983327</guid><dc:creator><![CDATA[DStefan]]></dc:creator><pubDate>Wed, 01 Feb 2006 17:40:00 GMT</pubDate></item><item><title><![CDATA[Reply to Funktionsaufrufe on Fri, 03 Feb 2006 10:45:37 GMT]]></title><description><![CDATA[<pre><code>map&lt;string,pair&lt;Command*,Command::Command_Fun&gt; &gt; FnMap;
FnMap[&quot;A1&quot;]=make_pair(new A,A::function1);
</code></pre>
<p>--&gt; error C2440: 'Initialisierung': 'void (__thiscall A::* const )(void)' kann nicht in 'Command::Command_Fun ' konvertiert werden<br />
Umwandlung von der Basis in die Ableitung erfordert 'dynamic_cast' oder 'static_cast'.<br />
Wie soll der Functionpointer korrekt gesetzt sein, wenn Basispointer auf Funktion in abgeleiteter Klasse zeigt?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/984851</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/984851</guid><dc:creator><![CDATA[Theresa]]></dc:creator><pubDate>Fri, 03 Feb 2006 10:45:37 GMT</pubDate></item></channel></rss>