Archiv verlassen und diese Seite im Standarddesign anzeigen : 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?
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
In C++ würde man das anders lösen:
#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
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
Wahrscheinlich, probiers einfach mal.
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
locus vivendi
01-09-2005, 16:03
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.
Puoah! Erst einmal vielen Dank für Deine Antwort. ;)
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
Also hier wäre mal eine solche, nicht funktionierende "Lösung":
#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...
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
locus vivendi
02-09-2005, 11:42
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.
anda_skoa
02-09-2005, 12:14
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,
_
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. :(
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
Powered by vBulletin® Version 4.2.5 Copyright ©2025 Adduco Digital e.K. und vBulletin Solutions, Inc. Alle Rechte vorbehalten.