Kopie einer Klasse unter anderem Namen



  • Im Projekt gibt es schon einen INI-File-Parser für die Konfigurationsdatei. Hier ist der Filename, der Parser und die Daten static und die Objekte beziehen sich auf eine INI-Sektion. Da hier an einer Here-Dokument-Funktionalität gearbeitet wird ist Cut-Copy-Paste sch...!

    Jetzt brauche ich Zugriff auf ein weiteres INI-File welches aber keine Konfigurationsdaten, sondern Code-Fragmente enthält!

    Funktional das gleiche, logisch und thematisch völlig unterschiedlich!

    !konkrete! Vorschläge?

    Danke
    Peanut

    [ Dieser Beitrag wurde am 13.05.2003 um 15:46 Uhr von Peanut editiert. ]



  • Nicht schön, aber geht!

    #include <iostream>
    #include <string>
    
    using namespace std;
    
    template<class T>
    class tmpl {
      static string name;
      public:
        string what(){ return name; };
        tmpl(string str=""){ name=str; };
    };
    
    typedef int classa;
    typedef bool classb;
    
    string tmpl<classa>::name;
    string tmpl<classb>::name;
    
    int main(int argc, char ** argv, char ** env){
      tmpl<classa> testa("a");
      tmpl<classb> testb("b");
      cout << testa.what() << endl;
      cout << testb.what() << endl;
    }
    

    Solange man genug "billige" Typen hat...

    Ihr wollt mich das nicht wirklich benutzen lassen, oder??



  • #include <iostream>
    #include <string>
    
    using namespace std;
    
    class tmpl {
      string name;
      public:
        string what(){ return name; } //nach memberfunktionen kein ; hintun!
        tmpl(const string &str) : name(str) {}
    }; //nur nach klassen, strukturen, unions, etc.
    
    int main(int argc, char ** argv, char ** env){
      tmpl testa("a");
      tmpl testb("b");
      cout << testa.what() << endl;
      cout << testb.what() << endl;
    }
    

    wie wär's damit?
    entweder ich hab was falsch verstanden, oder du: kennst du den unterschied zwischen Klasse und Instanz?



  • Original erstellt von davie:
    **
    entweder ich hab was falsch verstanden, oder du: kennst du den unterschied zwischen Klasse und Instanz?**

    Du hast was falsch verstanden!
    Probier folgende main, dieses Verhalten ist gewünscht!

    int main(int argc, char ** argv, char ** env){
      tmpl<classa> testa("a");
      tmpl<classb> testb("b");
      tmpl<classa> testc("c");
      tmpl<classb> testd("d");
      cout << testa.what() << endl;
      cout << testb.what() << endl;
      cout << testc.what() << endl;
      cout << testd.what() << endl;
    
      tmpl<classa> teste;
      cout << teste.what() << endl;
      cout << testc.what() << endl;
      cout << testa.what() << endl;
    }
    

    So sollte es klarer sein, oder?

    [ Dieser Beitrag wurde am 13.05.2003 um 16:52 Uhr von Peanut editiert. ]

    [ Dieser Beitrag wurde am 13.05.2003 um 16:53 Uhr von Peanut editiert. ]



  • wie wäre es mit einer static std::map oder einem std::set?

    #include <map>
    #include <string>
    using namespace std;
    
    class x {
       static map<string,string> vals;
       string name;
    public:
       x (const std::string &name_, const std::string &wert) : name(name_) {
          vals[name] = wert;
       }
       x (const std::string &name_) : name(name_) {}
    
       /*const*/ std::string/* &*/get_val() const { return vals[name]; }
    };
    map<string,string> x::vals;
    
    int main () {
    
       x inifile ("ini", "blub");
       x datafile ("data", "blob");
    
       cout << x("data").get_val() << endl;
       cout << x("ini").get_Val() < endl;
    }
    

    nur als beispiel.
    es gibt 1000 ander möglichkeiten, kommt halt darauf an, was du genau willt: erweiterbarkeit, wartbarkeit, einfachheit, schnelle implementierung etc.



  • Original erstellt von davie:
    wie wäre es mit einer static std::map oder einem std::set?

    Du bist leider an meinem Problem vorbei! Nochmal Klartext:
    -Habe funktionierende Klasse.
    -Klasse enthält statische Elemente.
    -Benötige selbe Funktionalität nocheinmal mit "eigenen" statischen Elementen

    Bis dann...
    Peanut



  • wenn es neue statische elemente sind können die funktionen, die du schon hast ja gar nichts über sie wissen?!
    zeig mal ein schönes beispiel, damit ich mir was drunter vorstellen kann - und keine umschreibungen.
    wahrscheinlich kann man dein problem auf ganz andere weise auch noch lösen...

    oder heute ist einfach nicht mein tag 🙄



  • OK, nah an der realität (nur so aufgeschrieben, kein kompilierbarer Code!):

    /// ini-File verarbeitende Classe
    class config{ 
      static string filename;
      static map< string section, map<string key, string value> > data;
      static bool parser(); //liesst filename-ini-file zeilenweise in data-map ein
      /// [section]
      /// key=value
      ///...
    
      string section; // nicht static!
      public:
      static setFilename( string str ):filename(str){parser()};
    
      config(string str):section( str ){};
      string get(string str){
        return data[section][str];
      }
    };
    
      void dbfct(void){
        config cfg("db");
        connection.connect("", cfg.get("host"), cfg.get("uid"), cfg.get("pass"));
        connection.select_db(cfg.get("DB"));
        ...
      }
    
      int main(void){
        config::setFilename("/etc/myconfig");
        config cfg("main");
        setuid(cfg.get["uid"].c_str()) || exit(1);
        dbfct();
      }
    

    Jetzt soll ausser /etc/myconfig noch ein weitere INI-File wie oben gezeigt zugänglich gemacht werden. Meine Idee war nun dieses Dublizieren der Klasse durch ein Template desses Template-Parameter ignoriert wird zu erreichen:

    template<class t>
    class config
      static string filename;
      static map< string section, map<string key, string value> > data;
      static bool parser();
    
      string section; // nicht static!
      public:
      static setFilename( string str ):filename(str){parser()};
    
      config(string str):section( str ){};
      string get(string str){
        return data[section][str];
      }
    }
    
    typedef int configuration;
    typedef bool codefragments;
    
    int main(void){
      config<configuration>::setFilename("/etc/myconfig");
      config<configuration> cfg("main");
      setuid(cfg.get["uid"].c_str()) || exit(1);
    
      config<codefragments>::setFilename(cfg.get("snippetfile"));
      config<codefragments> snippet["unauth"];
      cout << snippet.get("head")
           << snippet.get("body_head")
           << snippet.get("mainform")
           << snippet.get("body_footer");
    }
    

    So und hierfür suche ich entweder die Experten-Meinug "Das ist OK so!" oder "Nein, ein solches Problem lösst man indem man ..." (die Punkte sollten durch was sinnvolles ersetzt werden 😉 )

    Ist jetzt klar um was es geht?

    [ Dieser Beitrag wurde am 14.05.2003 um 00:07 Uhr von Peanut editiert. ]



  • Also ich hab mit dem kompletten Design so ... gewisse Anlaufschwierigkeiten ... zumindest finde ich es etwas ungewoehnlich !

    Also zum prinzipiellen Problem .... du willst die Daten aus einer ini-Datei,aus /etc/myconfig auslesen, und bestimmte Eintraege (DB,host,uid,pass) haben. Und fuer dein Programm kommt nu noch ne weitere Datei hinzu, wo du auch paaar bestimmte EIntraege(head,body_head ...) draus brauchst.

    Meine erste Frage, warum die statischen komponenten ? hat das nen besonderen Hintergrund ?

    2. Frage ... die Ini Dateien haben den selben aufbau ? Ich denk mal ja ....

    Strukturell wuerd ich so vorgehen!

    1. eine klasse, das Zeielnweisse aus dateien lesen kann (dein Ini-file ist ne Zeilen-orientierte Text-Datei). Heisser Kanditat: ifstream

    2. ne Klasse, die die Infos in strukturierter Form aus folgen von Zeilen interpretieren kann ... mit 1. als membervariable oder 1. als Basisklasse

    3. ne klasse, die Infos in der gewuenschten Form im Speicher halten kann, in deinem Fall ne Art Dictionary in der Form Key:Value (beides strings, oder du arbeitest mit internen IDs fuer deine Special-Strings(uid,host,pass)). Hier kann man ganz gut Maps zu verwenden .... Vielleicht noch ne Unterteilung in die einzelnen sections .... als Submaps realisiert ...

    4. ne Klasse, die die Faehigkeiten aller deiner vorherigen klassen kombiniert und fast das tut was du willst ... mit 2. und 3. als member ... mit ner parse( const char * astr_filename) Funktion, die DIr alle erkannten EIntraege aus der ini Datei rausliest und in den Container schreibt .... und mit ner get_property(const char * astr_key, const char * astr_section) Funktion, die nach gewuenschten einstellungen in dem Container suchen kann ....
    DIe Parse Funktion vielleicht so ausgelegt, das man sie mehrmals aufrufen kann, und das sie die gefunden eintraege dem Container einfach hinzufuegt ....
    Ne entsprechende Behandlungsroutine natuerlich, falls eintraege doppelt vorkommen ....

    5. die Spezialklasse, als Ableitung von 4. die dann genau deine Speziellen Wuensche parametriesiert enthaelt .... also ini datei 1 und ini datei 2 fest verdrahtet, die das Parsen auf den Dateien schon beim konstruieren vornimmt ... und Memberfunktionen hat, die nach festverdrahteten Strings in den Property container suchen ... ala int get_uid(char ** ap_Value) ... oder so ....

    So wuerde ich zumindest vorgehen ....

    P.S. mer die /etc/myconfig parsen will, will meist auch etwas mit mysql anfangen .... hast dir mal die MySQL-C API (die MySQLC++ dann sicher auch) angeschaut, da gibt es zumindtest routinen, wo du die einstellungen, die der mysql client schon ausgelesen (geparst) hat, schon abfragen kann. koennte dir vielleicht das parsen der /etc/myconfig ersparen ...

    Ciao ...

    [ Dieser Beitrag wurde am 14.05.2003 um 12:14 Uhr von RHBaum editiert. ]



  • Original erstellt von RHBaum:
    Also ich hab mit dem kompletten Design so ... gewisse Anlaufschwierigkeiten ... zumindest finde ich es etwas ungewoehnlich !

    Ja, ungewöhnlich finde ich es auch! Aber der Increment-Operator verwendet doch auch einen nicht ausgewerteten int-Parameter zur Pre- und Post-Inkrement unterscheidung! Ich finde das ist vergleichbar.

    Also zum prinzipiellen Problem .... du willst die Daten aus einer ini-Datei,aus /etc/myconfig auslesen, und bestimmte Eintraege (DB,host,uid,pass)
    haben. Und fuer dein Programm kommt nu noch ne weitere Datei hinzu, wo du auch paaar bestimmte EIntraege(head,body_head ...) draus brauchst.
    Meine erste Frage, warum die statischen komponenten ? hat das nen besonderen Hintergrund ?

    Soooo "bestimmt" sind die Einträge nicht! Jede Klasse die was an Einstellungen braucht bekommt im INI-File ihre Section und der entsprechende Entwickler kann da an Infos ablegen was er will. Keiner muss sich über die Eindeutigkeit seines Parameternamens Gedanken machen weil der Parameter in SEINER Section steht. In der Klasse holt man sich einfach via

    Config mysettings("mysectionname");
    

    seinen Teil der Konfiguration und hat Zugriff auf seine Einstellungen.

    I/O-Operationen sind EXTREM teuer! Das ganze INI-File wird einmal via mmap geholt, verarbeitet und steht dann in jeder Instanz zur verfühgung! Evtl. kann man den Instanzen Zeiger auf die Daten verpassen und je nach Bedarf auf unterschiedliche Daten verweisen. Der Parser könnte die Map erzeugen und einhängen, man bräuchte eine weitere Map für den Use-Counter und der Destruktor kann die Daten bei use-count==0 löschen, ähhh ne es kann ja sein das die Daten später nochmal gebraucht werden... ich kann die Daten-Map nieeee löschen 😞

    2. Frage ... die Ini Dateien haben den selben aufbau ? Ich denk mal ja ....
    Sonst währe es alles Quark, nee?

    Strukturell wuerd ich so vorgehen!
    1. eine klasse, das Zeielnweisse aus dateien lesen kann (dein Ini-file ist ne Zeilen-orientierte Text-Datei). Heisser Kanditat: ifstream

    Realisiert mit mmap. Da Konstrukte der Form

    a=aaaaaaa\<Zeilenumbruch>
    auchNochAaaaaaaaaaa\<Zeilenumbruch>
    aaaaaaaa
    

    möglich sein sollen (a<<EOF kommt auch noch ;)) ist die Datei zwar Zeilen-orientiert aber die Daten nicht!

    2. ne Klasse, die die Infos in strukturierter Form aus folgen von Zeilen interpretieren kann ... mit 1. als membervariable oder 1. als Basisklasse
    3. ne klasse, die Infos in der gewuenschten Form im Speicher halten kann, in deinem Fall ne Art Dictionary in der Form Key:Value (beides strings, oder du arbeitest mit internen IDs fuer deine Special-Strings(uid,host,pass)). Hier kann man ganz gut Maps zu verwenden .... Vielleicht noch ne Unterteilung in die einzelnen sections .... als Submaps realisiert ...

    map<string, map<string, string>
    

    4. ne Klasse, die die Faehigkeiten aller deiner vorherigen klassen kombiniert und fast das tut was du willst ... mit 2. und 3. als member ... mit ner parse( const char * astr_filename) Funktion, die DIr alle erkannten EIntraege aus der ini Datei rausliest und in den Container schreibt .... und mit ner get_property(const char * astr_key, const char * astr_section) Funktion, die nach gewuenschten einstellungen in dem Container suchen kann ....
    DIe Parse Funktion vielleicht so ausgelegt, das man sie mehrmals aufrufen kann, und das sie die gefunden eintraege dem Container einfach hinzufuegt ....
    Ne entsprechende Behandlungsroutine natuerlich, falls eintraege doppelt vorkommen ....

    Ja, und die Klasse nenne ich dann Config... so habe ich es ja...

    5. die Spezialklasse, als Ableitung von 4. die dann genau deine Speziellen Wuensche parametriesiert enthaelt .... also ini datei 1 und ini datei 2 fest verdrahtet, die das Parsen auf den Dateien schon beim konstruieren vornimmt ... und Memberfunktionen hat, die nach festverdrahteten Strings in den Property container suchen ... ala int get_uid(char ** ap_Value) ... oder so ....
    Nachtigall ich hoehr dir trappsen... Habe bisher eher C Programmiert und mir fehlt die Objekt denke ein wenig.
    Als ich geschrieben habe (erstes Posting 2.) Vererbung drückt ein "ist ein"-Verhältniss aus, Bjarne sagt bescheiss nie deinen Compiler und die beiden Klassen haben nichts miteinander zu tun 😞 hätte ja mal einer sagen können "Ja, aber wenn sie beide die gleiche Funktion erfüllen, habe sie w*****einlich die gleiche Basisklasse!". Also Basisklasse IniFile, Subklasse

    Config:public IniFile
    

    , weil die Konfiguration "ist ein" IniFile, und Subklasse

    Snippets:public IniFile
    

    , weil die Snippets auch ein IniFile sind. Ja das passt... schön!

    So wuerde ich zumindest vorgehen ....
    Ja, ich glaube ich jetzt auch 😉

    P.S. mer die /etc/myconfig parsen will, will meist auch etwas mit mysql anfangen ....
    Ja neee, der Name ist nur spontan gewählt für "meine Konfiguration" halt. Mysql benutzen wir zwar auch, hat aber nichts mit dem Konfigfile zu tun...

    Ciao ...
    Yepp, und danke nochmal für den Schupps, den Rempler, das Tracktor-Pushing in die richtige Richtung. Manchmal braucht man halt so einen Wink mit dem Zaunpfahl, Dachpfetten, ...


Anmelden zum Antworten