Kann es eine Funktion ExecProcedure(string name) geben?



  • Oh,

    ich habe gar nicht gesehen, dass in euren Funktionen die aufzurufenden Prozeduren bekannt sein müssen. Angenommen, sie sind nicht bekannt - fragt mich jetzt nicht wofür das gut ist - aber gibt es da auch eine Lösung?



  • Zu deiner switch-Frage: Nein, if ist da wohl erste Wahl.

    Zu deinem zweiten Post: Wie willst du etwas aufrufen, von dem du nicht weißt wie es heißt und wo es sich befindet? 😉

    Womöglich geht es mit plattformspezifischen Mittelchen (ich denke da an DLLs), aber mit Standardmitteln wohl nicht.



  • c++Beginner schrieb:

    Oh,

    ich habe gar nicht gesehen, dass in euren Funktionen die aufzurufenden Prozeduren bekannt sein müssen. Angenommen, sie sind nicht bekannt - fragt mich jetzt nicht wofür das gut ist - aber gibt es da auch eine Lösung?

    Was soll eine unbekannte Funktion Deiner Meinung nach denn tun ?

    Gruß,

    Simon2.



  • Sagen wir es so: Es ist möglich, aber wenn die Funktion bzw der SPeicher nicht existiert bzw nicht belegt ist, hast du ein Problem (:

    Das meinte ich mit der heiklen Angelegenheit.



  • Was soll eine unbekannte Funktion Deiner Meinung nach denn tun ?

    Keine unbbekante Funktion. Ich meinte, dass ich einmal eine Methode "ExecProcedure" definieren muss und mich dann aber nicht darum kümmern muss, jedes Mal einen neuen Eintrag in der Map zu erzeugen, wenn eine Funktion hinzukommt - dann ist die switch-Variante meistens sogar kürzer.



  • c++Beginner schrieb:

    Was soll eine unbekannte Funktion Deiner Meinung nach denn tun ?

    Keine unbbekante Funktion. Ich meinte, dass ich einmal eine Methode "ExecProcedure" definieren muss und mich dann aber nicht darum kümmern muss, jedes Mal einen neuen Eintrag in der Map zu erzeugen, wenn eine Funktion hinzukommt - dann ist die switch-Variante meistens sogar kürzer.

    Du musst die Funktionen die du verwendest auch bekannt machen. Sei es nun das du jedesmal den Code deiner ExecProcedure um einen neuen if/else-Fall erweiterst oder einen neuen Eintrag in eine map einfügst. Ohne geht es nicht (Eine Funktion hat keine Namen in dem Sinne, das dieser zur Laufzeit noch bekannt wäre).

    Irgendwie musst du also deinen Code anpassen.

    Das sauberste ist aber tatsächlich die Lösung mit der map.

    cu André



  • c++Beginner schrieb:

    Was soll eine unbekannte Funktion Deiner Meinung nach denn tun ?

    Keine unbbekante Funktion. Ich meinte, dass ich einmal eine Methode "ExecProcedure" definieren muss und mich dann aber nicht darum kümmern muss, jedes Mal einen neuen Eintrag in der Map zu erzeugen, wenn eine Funktion hinzukommt - dann ist die switch-Variante meistens sogar kürzer.

    nö, ist sie nicht, da du ja strings vergleichen musst, hast du nicht mal ne switch-Anweisung:

    bool ExecProcedure(const std::string& str)
    {
        if(str == "hallo") {  // zeile 1
            hallo();          // zeile 2
            return true;      // zeile 3
        }                     // zeile 4
        else if(str == "answer") {
            answer();
            return true;
        }
        else
            return false;   
    }
    

    das sind jeweils 4-5 Zeilen, wenn es ordentlich eingerückt und übersichtlich sein soll.

    Die Map-Variante benötigt nur 1 Zeile:

    functions.insert( make_pair("answer", &answer) );
    

    und gerade wenn die Funktionsanzahl 10+ erreicht, tut Beispiel 1 schon in den Augen weh. Und hinzufügen musst du die Funktionen so oder so!

    - Edit: zu langsam -



  • Auch ordentlich:

    bool ExecProcedure(const std::string& str)
    {
        if(str == "hallo")    // zeile 1
            hallo();          // zeile 2
        else if(str == "answer")
            answer();
        else
            return false;  
        return true;
    }
    


  • So, ich habe mal etwas ausprobiert, obwohl ich kein Fan von globalen Variablen bin. Ich übernehme für den Code auch keine Garantien:

    Ziel des Codes ist es, mit möglichst wenig gegenseitigen Wissen Funkionen über einen Namen aufzurufen:

    // main.cpp

    #include "exec_fn.h"
    
    int main()
    {
      exec::ExecuteFunction("ShowA");
      exec::ExecuteFunction("ShowB");
      exec::ExecuteFunction("ShowA");
      exec::ExecuteFunction("wait");
    }
    

    // exec_fn.h

    #if !defined(EXEC_FN_HEADER)
    #define EXEC_FN_HEADER
    
    #include <string>
    
    namespace exec
    {
      typedef void (*function_type)(); 
    
      void Register(const std::string& functionName, function_type function);
      void ExecuteFunction(const std::string& functionName);
      class RegisterFunction
      {
        public:
          RegisterFunction(const std::string& functionName, function_type function)
          {
            Register(functionName, function);
          }
      };
    }
    
    #endif
    

    // exec_fn.cpp

    #include "exec_fn.h"
    #include <map>
    
    namespace exec
    {
      std::map<std::string, function_type>& GetFunctionMap()
      {
        static std::map<std::string, function_type> functionMap;
        return functionMap;
      }
    
      void Register(const std::string& functionName, function_type function)
      {
        std::map<std::string, function_type>& functionMap = GetFunctionMap();
        if(functionMap.find(functionName) == functionMap.end())
          functionMap[functionName] = function;
      }
    
      void ExecuteFunction(const std::string& functionName)
      {
        std::map<std::string, function_type>& functionMap = GetFunctionMap();
        std::map<std::string, function_type>::iterator pos = functionMap.find(functionName);
        if(pos != functionMap.end())
          (pos->second)();
      }
    }
    

    Zudem noch 3 weitere Dateien die aber alle den gleichen Aufbau haben (Eine void-Funktion ohne Parameter, eine globale Variable...). Ich zeige hier nur die Implementierung von der wait.h/wait.cpp.

    // wait.h

    #if !defined(WAIT_HEADER)
    #define WAIT_HEADER
    void wait();
    #endif
    

    // wait.cpp

    #include "exec_fn.h"
    #include <iostream>
    
    void wait()
    {
      std::cin.clear();
      std::cin.ignore(std::cin.rdbuf()->in_avail());
      std::cin.get();
    }
    
    // Hiermit wird die wait-Funktion registriert
    exec::RegisterFunction wait_("wait", &wait);
    

    Die restlichen Header/Sourcen kann man sich wohl selbst ausdenken...

    Ob man dies als Sauber bezeichnen kann wage ich aber zu bezweifeln (Getestet unter VC++ 2005).

    cu André



  • c++Beginner schrieb:

    Was soll eine unbekannte Funktion Deiner Meinung nach denn tun ?

    Keine unbbekante Funktion. Ich meinte, dass ich einmal eine Methode "ExecProcedure" definieren muss und mich dann aber nicht darum kümmern muss, jedes Mal einen neuen Eintrag in der Map zu erzeugen, wenn eine Funktion hinzukommt ..

    Ach so: Du möchtest also eine "automatische Externalisierung", sobald Du eine Funktion hinzufügst.

    Ich weiß gar nicht, ob mir das erstrebenswert erschiene .... aber da der Compiler das nicht kann, geht's halt auch nicht.

    Gruß,

    Simon2.


Anmelden zum Antworten