Anzeige:
Ergebnis 1 bis 11 von 11

Thema: DefaultKeyMap

  1. #1
    Registrierter Benutzer
    Registriert seit
    29.02.2004
    Beiträge
    113

    DefaultKeyMap

    Hey Amigos, wie geht's?

    Da ich leider C++ nicht wirklich beherrsche, aber anhand vorhandener Python-Beispiele lernen möchte, habe ich folgende Frage: Wie sähe folgende Klasse in C++ implementiert aus?
    Code:
    class DefKeyDict(dict):
      def __init__(self, defkey, dct=dict()):
        dict.__init__(self, dct)
        self.defkey =  defkey
      def __getitem__(self, key):
        try:
          return dict.__getitem__(self, key)
        except KeyError:
          return dict.__getitem__(self, self.defkey)
    Natürlich würde ich sie von map<string, irgendetwas> ableiten, und dort den operator[] überladen. Aber das ist leider das einzige, was mir dazu einfällt. Funktionierenden Code habe ich nicht erreicht!

    Vielen Dank für eure Antworten!
    Gruß,
    /dev

  2. #2
    Registrierter Benutzer
    Registriert seit
    25.10.2004
    Beiträge
    819
    In C++ würde man das anders lösen:
    Code:
    #include <map>
    #include <string>
    using namespace std;
    
    template<typename T> class MyDict
    {
      public:
        MyDict(string defkey);
        T get(string key);
        void set(string key, T value);
      private:
        map<string,T> m_map;
        string m_defkey;
    };
    
    template<typename T> MyDict<T>::MyDict(string defkey)
        : m_defkey(defkey)
    {}
    
    template<typename T> inline T MyDict<T>::get(string key)
    {
        if (m_map.find(key) == m_map.end()) {
            return m_map[m_defkey];
        } else {
            return m_map[key];
        }
    }
    
    template<typename T> inline void MyDict<T>::set(string key, T value)
    {
        m_map[key] = value;
    }
    Du kannst einen operator[] definieren, der entweder eine Referenz auf m_map[m_defkey] oder m_map[key] zurückgibt, dann hast du in etwa das Python-äquivalent

  3. #3
    Registrierter Benutzer
    Registriert seit
    29.02.2004
    Beiträge
    113
    Ach so, über eine Memberklasse? Warum auch nicht, aber wäre ein Ableiten von map<string, T> nicht besser[tm]? Schließlich hätte ich dann eine spezialisierte Map und nicht irgendeine Klasse?

    Vielen Dank für deine rasche Antwort!
    Gruß,
    /dev

  4. #4
    Registrierter Benutzer
    Registriert seit
    25.10.2004
    Beiträge
    819
    Wahrscheinlich, probiers einfach mal.

  5. #5
    Registrierter Benutzer
    Registriert seit
    29.02.2004
    Beiträge
    113
    Hm, ich kriege es im Moment einfach nicht gebacken. Er akzeptiert im Moment nicht einmal die Deklaration meiner abgeleiteten Klasse! Es liegt nicht an der Idee selbst, sondern daran, daß ich einfach kein C++ kann. Wie sähe denn eine C++ implementierung aus, die sich (möglichst) genau an die Python-Variante hält?

    Gruß,
    /dev

  6. #6
    Registrierter Benutzer
    Registriert seit
    23.05.2004
    Beiträge
    592
    Da ich leider C++ nicht wirklich beherrsche, aber anhand vorhandener Python-Beispiele lernen möchte, habe ich folgende Frage: Wie sähe folgende Klasse in C++ implementiert aus?
    Erst mal herzlichen Glückwunsch dazu, dass du C++ lernen willst. Ich selber nehme mir immer mal wieder vor, eine andere Sprache als C++ zu lernen, aber mach es dann letztendlich doch nicht.

    Ob Python-Beispiele in C++ umsetzen der beste Weg ist, um C++ zu lernen, da bin ich mir nicht so sicher. Vielleicht ist etwas Tuturial-artiges doch besser? Es gibt ja doch ein paar Eigenarten von C++, die man möglichst lernen sollte, und ich könnte mir vorstellen, dass das etwas auf der Strecke bleibt wenn man immer Python im Hinterkopf hat - was mich zum folgenden bringt:
    Natürlich würde ich sie von map<string, irgendetwas> ableiten, und dort den operator[] überladen.
    Das ist nämlich so eine Sache, ganz natürlich ist das Ableiten von den Standard-Containern, also auch von map, nämlich nicht. Z.b. haben die keine virtuellen Funktionen. Um fair zu sein, möglicherweise ist dein Beispiel etwas wo man tatsächlich ableiten würde.

    Falls du die nicht schon kennst, hier ein paar Ressourcen die gerade für Anfänger (aber nicht nur) recht nützlich sind:
    http://www.icce.rug.nl/documents/cpp.shtml
    http://www.research.att.com/~bs/homepage.html
    http://www.parashift.com/c++-faq-lite/
    und ferner http://www.cetus-links.org, wo alle diese Seiten verlinkt sind. Leider sind dort viele Einträge nicht mehr aktuell.

  7. #7
    Registrierter Benutzer
    Registriert seit
    29.02.2004
    Beiträge
    113
    Puoah! Erst einmal vielen Dank für Deine Antwort.

    Zitat Zitat von locus vivendi
    Ich selber nehme mir immer mal wieder vor, eine andere Sprache als C++ zu lernen, aber mach es dann letztendlich doch nicht.
    Naja, mit C++ bist du auch recht gut gerüstet. Ich habe mich bisher immer darum gedrückt, weil ich für mich OO mit JAVA und schließlich Python besser lernen konnte. C++ ist IMHO brauchbar, wenn du weißt, was du willst. Aber parallel dazu auch noch das Konzept der OO zu lernen, dafür war die Sprache für mich irgendwie überfrachtet. Heute denke ich anders: JAVA ist mir heute persönlich viel zu eingeschränkt, Python ist zwar extrem geil, aber das Fehlen von Deklarationen schwärzt das Gesamtbild dann doch etwas.

    Ob Python-Beispiele in C++ umsetzen der beste Weg ist, um C++ zu lernen, da bin ich mir nicht so sicher.
    Die Idee mit dem Indexoperator habe ich aus Stroustrups Buch. Direkt sowas wie Operatoren gibt es in Python nicht, es gibt halt einfach spezielle Methoden, die von der PVM bei Bedarf aufgerufen werden, so etwa __getitem__, __add__ et al.

    Das ist nämlich so eine Sache, ganz natürlich ist das Ableiten von den Standard-Containern, also auch von map, nämlich nicht.
    Naja, ich habe mir halt gedacht, ich habe entweder eine Klasse mit Defaultkeys oder eine Klasse mit Defaultkeys, die sich auch noch überall als Map einsetzen läßt. Letzere ist universeller und daher würde ich sie vorziehen.

    Z.b. haben die keine virtuellen Funktionen.
    Mist! Das ist genau so ein Unterschied, den ich immer übersehe. In C++ ist 'final' implizit, in Python und JAVA hingegen 'virtual'.

    Vielen Dank für die Links. Vielleicht gelingt dir das Beispiel ja noch. Ich mache jetzt mal Schluß für heute!

    Gruß,
    /dev

  8. #8
    Registrierter Benutzer
    Registriert seit
    29.02.2004
    Beiträge
    113
    Also hier wäre mal eine solche, nicht funktionierende "Lösung":
    Code:
    #include <map>
    #include <string>
    
    using namespace std;
    
    template<string, string> class DefKeyMap : public Map<string,string>
    {
      public:
        DefKeyMap(string defkey);
        string operator[](const string key);
      private:
        string defkey;
    };
    
    DefKeyMap::DefKeyMap(string defkey)
    {
      this.defkey = defkey;
    }
    
    string& DefKeyMap::operator[](const string key)
    {
      try {
        return Map<string,string>[key];
      } catch (...) {
        return Map<string,string>[defkey];
      }
    }
    Aus den Fehlermeldungen werde ich allerdings nicht wirklich schlau...
    Code:
    defkeymap.cpp:6: error: `struct std::basic_string<char, std::char_traits<char>, 
       std::allocator<char> >' is not a valid type for a template constant 
       parameter
    defkeymap.cpp:6: error: `struct std::basic_string<char, std::char_traits<char>, 
       std::allocator<char> >' is not a valid type for a template constant 
       parameter
    defkeymap.cpp:6: error: parse error before `<' token
    defkeymap.cpp:10: error: `std::string operator[](std::basic_string<char, 
       std::char_traits<char>, std::allocator<char> >)' must be a nonstatic member 
       function
    defkeymap.cpp:10: error: `std::string operator[](std::basic_string<char, 
       std::char_traits<char>, std::allocator<char> >)' must take exactly two 
       arguments
    defkeymap.cpp:11: error: parse error before `private'
    defkeymap.cpp:15: error: syntax error before `::' token
    defkeymap.cpp:20: error: syntax error before `::' token
    Gruß,
    /dev

  9. #9
    Registrierter Benutzer
    Registriert seit
    23.05.2004
    Beiträge
    592
    Hm, okay, da ist jetzt in fast jeder zweiten Zeile was falsch.
    Also ich zähle mal ein paar Punkte auf die anders gemacht werden:
    - Der Template der "Map" heißt "map" (oder std::map), in Kleinschreibung.
    - Das "template ..." vor deiner Klasse gehört da nicht hin. Du willst ja kein Template definieren, spezialisieren, oder instanzieren. Du willst eine ganz normale Klasse anlegen.
    - "this. ..." funktioniert nicht. this ist ein Zeiger, deshalb kommt nach this kein Punkt sondern ein "->".
    - In deinem Operator []: Das try/catch ist da falsch, weil der []-Operator der std::map das nicht-finden von Element nicht durch eine Ausnahme signalisiert.
    - ebenfalls zum Operator[]: Man kann nicht bei der Deklaration keine Referenz zurückgeben, aber bei der Definition eine Referenz.

    Wenn du alle diese Fehler ausbesserst, wird das Programm wahrscheinlich kompilierbar. Allerdings bin ich mir nicht so sicher, dass es das machen würde was du erwartest :-)
    Z.b. liefert der []-Operator der std::map niemals zurück, das er ein Element nicht finden konnte, sondern stattdessen legt er ein Default-konstruiertes Element mit dem Schlüssel an.

  10. #10
    Administrator Avatar von anda_skoa
    Registriert seit
    17.11.2001
    Ort
    Graz, Österreich
    Beiträge
    5.477
    Zitat Zitat von locus vivendi
    Z.b. liefert der []-Operator der std::map niemals zurück, das er ein Element nicht finden konnte, sondern stattdessen legt er ein Default-konstruiertes Element mit dem Schlüssel an.
    Du könntest stattdessen find() benutzen und den Rückgabewert mit end() vergleichen.

    Ciao,
    _
    Qt/KDE Entwickler
    Debian Benutzer

  11. #11
    Registrierter Benutzer
    Registriert seit
    29.02.2004
    Beiträge
    113
    Zitat Zitat von locus vivendi
    Hm, okay, da ist jetzt in fast jeder zweiten Zeile was falsch.
    Na immerhin...ich habe im Moment noch Beispiele, in denen das Verhältnis viel schlechter ist!

    - Das "template ..." vor deiner Klasse gehört da nicht hin. Du willst ja kein Template definieren, spezialisieren, oder instanzieren. Du willst eine ganz normale Klasse anlegen.
    Stimmt! Das hatte ich zuerst auch so...

    - "this. ..." funktioniert nicht. this ist ein Zeiger, deshalb kommt nach this kein Punkt sondern ein "->".
    Oh nein! Nicht schon wieder!

    Z.b. liefert der []-Operator der std::map niemals zurück, das er ein Element nicht finden konnte, sondern stattdessen legt er ein Default-konstruiertes Element mit dem Schlüssel an.
    Das steht ebenfalls so in [Stroustrup]. Leider sah ich den Wald vor lauter Bäumen nicht mehr.

    Zitat Zitat von anda_skoa
    Du könntest stattdessen find() benutzen und den Rückgabewert mit end() vergleichen.
    Ja, so werd ich das denn auch tun!

    Vielen Dank für eure Hilfe!

    Gruß,
    /dev

Lesezeichen

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •