Codevereinfachung



  • Hi,

    ich habe momentan so etwas in meinem Code:

    MyClass *CreateClass(const std::string& str)
    {
     if (str == "blub")
     {
      return new MyClassBlub();
     }
     else if (str == "bla")
     {
      return new MyClassBla();
     }
     else if (str == "foo")
     {
      return new MyClassFoo();
     }
    
     // ...
    
     return NULL;
    }
    

    Das klappt zwar perfekt, aber es ist natürlich nicht so "schön". Gibt es eine Möglichkeit das ganze über ein Array zu machen?

    Dann bräuchte ich nicht bei jeder Erweiterung ein neues "else if" einfügen.



  • Da gibts viele Wege. Vielleicht eine map von string nach Funktionszeiger.

    //Datei MyClassBlub.cpp
    MyClassBlub::MyClassBlubb()
    {
      ...
    };
    MyClassBlub* MyClassBlub::create()//static in MyClassBlub
    {
      return new MyClassBlub;
    }
    static bool registerClassRegisterBoolFlagHolderWorkaroundHack=MyClass::registerClass("blubb",&MyClassBlub::create);
    
    //MyClass.cpp
    bool MyClass::registerClass(string const& str,MyClass*(*c)())
    {
      theRegisterClassMap[str]=c;
    }
    MyClass* MyClass::CreateClass(const std::string& str)
    {
      MyClass*(*c)()=theRegisterClassMap[str];
      if(!c)
        return 0;
      return (*c)();
    }
    




  • Man muss sich allerdings immer überlegen was besser ist. Dein If-Zweig ist vielleicht nicht sehr ästhetisch, aber jeder wird die Funktion sofort ohne Probleme verstehen und Nachteile bei der Erweiterung hast du auch keine, in beiden Fällen müsstest du irgendwo die neue Klasse hinzufügen. Bei den If-Zweig bedarf das keiner großen Dokumentation um das hinzubekommen, bei einem komplizierteren Setup sieht das schon anders aus.

    In C++ brauche ich so etwas normal nicht, aber in C verwende ich folgendes Idiom (auf deinen Fall umgestrickt):

    Basis* create(const char *str)
    {
       static const struct {
          const char *name;
          Basis *(*create_it)();
       } creators[] = {
           { "bla", create_bla },
           { "foo", create_foo },
           { NULL, NULL }
       }, *cur = &creators[0];
    
       while(cur->name)
         if(!strcmp(cur->name, str))
            return cur->create_it();
       return NULL;     
    }
    

    Ist zwar noch sehr C-lastig, aber die Idee ist wohl klar: einfach ein Array mit String + Funktion zum erstellen und dann per Schleife durchgehen.


Anmelden zum Antworten