Alternative zu void* ? C++11
-
Hallo Community ich möchte eine Registry Klasse machen.
Es gibt ja 3 Arten von ValueTypes in Registry:
REG_SZ
REG_DWORD
REG_BINARYund Abarten von diesen drei:
REG_MULTI_SZ
REG_EXPAND_SZso habe ich mir gedacht, dass ich es mit Abstrakter Klassen mache
enum REG_TYPE { REG_SZ, REG_DWORD, REG_BINARY }; class Key { private: protected: HKEY hKey; std::wstring path; std::wstring KeyName; public: virtual void* read() = 0; virtual bool write(std::wstring name, void* value) = 0; /* * Je nachdem, welche Childclass kommt, wird value ein std::wstring oder DWORD */ virtual std::wstring getName() = 0; }; class KeySZ : public Key { private: std::wstring value; protected: public: bool write(std::wstring name, void* value); std::wstring getName() { return this->KeyName; } }; bool KeySZ::write(std::wstring name, void* value) { [...] LONG lRes = RegSetValueExW(this->hKey, name.c_str(),0,NULL,(const BYTE*)((std::wstring)value).c_str(),((std::wstring)value).length()); [...] }
Der Sinn meines Gedanken ist:
typedef std::map<std::wstring,Key> MKey; class RegTree { public: typedef std::map<std::wstring,RegTree> MTree; private: MKey Keys; MTree Trees; [...] };
Somit könnte ich einen Container erstellen, der alle drei Arten von RegKeys beinhaltet.
Hat jemand eine gute Idee das zu realisieren?
Mit freundlichen Grüßen
Sepultura
-
Warum glaubst du, dass es eine gute Idee ist das Typsystem zu umgehen und Strings, Binärdaten und ints in einen Topf zu schmeißen? Da wirst du doch definitiv durcheinander kommen.
KeySZ::write sollte einen string nehmen und keinen void *. Weiterhin würde ich die Vererbung komplett weglassen, das wird nur schaden. Wenn es denn sein muss, dann sollte KeySZ private von Key erben, damit die void -Variante von write nicht benutzbar ist, die ist allein für die KeyBinary-Variante reserviert, wobei dafür noch ein Parameter für die Länge der void-Daten fehlt.
Warum willst du eigentlich Keys verschiedener Typen in eine map tun? Die kann man doch nicht vernünftig benutzen.
-
Wieso nicht einfach
key.readSZ()
usw.?
-
nwp3 schrieb:
Warum glaubst du, dass es eine gute Idee ist das Typsystem zu umgehen und Strings, Binärdaten und ints in einen Topf zu schmeißen? Da wirst du doch definitiv durcheinander kommen.
KeySZ::write sollte einen string nehmen und keinen void *. Weiterhin würde ich die Vererbung komplett weglassen, das wird nur schaden. Wenn es denn sein muss, dann sollte KeySZ private von Key erben, damit die void -Variante von write nicht benutzbar ist, die ist allein für die KeyBinary-Variante reserviert, wobei dafür noch ein Parameter für die Länge der void-Daten fehlt.
Warum willst du eigentlich Keys verschiedener Typen in eine map tun? Die kann man doch nicht vernünftig benutzen.Wenn ich die Vererbung entferne, müsste ich also 3 Key Container für RegTree machen.
Damit würden auch drei Iteratoren entstehen, um alle Keys nacheinander durchgehen zu können.
-
Denk nicht in den Daten! Wenn du in Daten denkst, wird das nichts mit "schönem" C++ und du brauchst type erasure.
Denk in Eigenschaften! Wenn du über die Keys iterierst, WAS musst du dann machen?
Und das packst du in eine virtuelle Funktion.
-
Nathan schrieb:
wird das nichts mit "schönem" C++ und du brauchst type erasure.
type erasure ist schönes C++.
-
theeraser schrieb:
Nathan schrieb:
wird das nichts mit "schönem" C++ und du brauchst type erasure.
type erasure ist schönes C++.
Nein.
Die Implementierung ist zwar herrlich ( ), aber es ist kein schönes C++ im Anwendercode.
-
Ihr meint, ich soll Templates verwenden?
-
Sepultura schrieb:
Ihr meint, ich soll Templates verwenden?
Nein.
-
Nathan schrieb:
Nein.
Die Implementierung ist zwar herrlich ( ), aber es ist kein schönes C++ im Anwendercode.Genau umgekehrt. Die Implementierung von Type Erasure braucht relativ viel Boilerplate-Code und bei komplexeren Dingen ziemliche TMP-Tricks, aber die Anwendung könnte kaum schöner sein.
Bestes Beispiel:
std::function
Schlechteres Beispiel:boost::any
-- nicht weil die Klasse nicht gut entwickelt ist, sondern weil Leute sie einsetzen ohne sie zu benötigen.Was nicht gut ist, ist explizite Fallunterscheidung (switch, if-else, RTTI). Gut ist Polymorphie.
-
Hallo
KeySZ::KeySZ(HKEY root, std::wstring subkey, bool readonly) { this->subkey = subkey; LONG lRes; if (readonly) lRes = RegOpenKeyExW(root, subkey.c_str(), 0, KEY_READ, &this->hKey); else lRes = RegOpenKeyExW(root, subkey.c_str(), 0, KEY_ALL_ACCESS, &this->hKey); if (lRes != ERROR_SUCCESS) throw "COULD NOT OPEN"; TCHAR buffer[512]; RegQueryValueExW(this->hKey, TEXT("Installer Language"), 0, 0, (BYTE*)buffer, (DWORD*)512); std::wcout << buffer << std::endl; }
Ausgeführt wird der code so:
KeySZ test(HKEY_CURRENT_USER, TEXT("Software\\pidgin"), false);
Warum wirft RegQueryValueExW eine Zugriffsverletzung?
-
Sepultura schrieb:
Alternative zu void* ? C++11
WARUM?
Was willst Du erreichen? Welchen Zweck verfolgst Du? Für jeden Zweck können wir Dich totwerfen mit hunderten von Lösungen, die ihrerseits je nach anderem Zweck besser oder schlechter wären.
Viele von uns wollen einfach nicht glauben, daß Du die Windows-Registry nachbilden willst. Die kommt nämlich direkt aus der Hölle.
Mach am besten, was Nathan und Nexus sagen. Die sind mir in vielen bisherigen Threads saupositiv aufgefallen, wie sie schwach anfangen und sich miteinander aufs Optimum aufschaukeln und nicht jemanden belästigend "belehren", sondern einfach helfen.
Außer hier gerade mal. Nuja, passiert.
Passiert mich auch (jetzt nämlich zum Beispiel!). Kannst die Registry nicht sinnvoll abbilden. "'Ääätsch!". Kannst aber schon irgendwelche Proxy-Objekte da ablegen und holen. Mehr aber nicht bitte. Und die schon sind zu objektorientiert. Lass es doch einfach bei den Zugriffsfunktionen. Die kannste ein wenig schmirgeln bei Bedarf.
-
Sepultura schrieb:
KeySZ::KeySZ(HKEY root, std::wstring subkey, bool readonly) { this->subkey = subkey; LONG lRes; if (readonly) lRes = RegOpenKeyExW(root, subkey.c_str(), 0, KEY_READ, &this->hKey); else lRes = RegOpenKeyExW(root, subkey.c_str(), 0, KEY_ALL_ACCESS, &this->hKey); if (lRes != ERROR_SUCCESS) throw "COULD NOT OPEN"; TCHAR buffer[512]; RegQueryValueExW(this->hKey, TEXT("Installer Language"), 0, 0, (BYTE*)buffer, (DWORD*)512); std::wcout << buffer << std::endl; }
Ausgeführt wird der code so:
KeySZ test(HKEY_CURRENT_USER, TEXT("Software\\pidgin"), false);
Warum wirft RegQueryValueExW eine Zugriffsverletzung?
Wahrscheinlich weil dort
RegQueryValueExW( ..., (DWORD*)512);
steht. Hat der Compiler dort keine Warnung ausgeworfen? Dort lässt Du die Funktion auf ein Stück Speicher an der Adresse 512 zugreifen.
Du meinst sicher:DWORD len = 512; RegQueryValueExW(this->hKey, TEXT("Installer Language"), 0, 0, (BYTE*)buffer, &len);
Und vergesse nicht, den Returnwert der Funktion auszuwerten!
-
Nexus schrieb:
Nathan schrieb:
Nein.
Die Implementierung ist zwar herrlich ( ), aber es ist kein schönes C++ im Anwendercode.Genau umgekehrt. Die Implementierung von Type Erasure braucht relativ viel Boilerplate-Code und bei komplexeren Dingen ziemliche TMP-Tricks
Sagte ich doch: schönes C++. :p
Ich persönlich liebe es solche Probleme mit allen verfügbaren Mitteln zu lösen, ob es nun TMP-Hacks, Makros oder ähnliches ist., aber die Anwendung könnte kaum schöner sein.
Bestes Beispiel:std::function
Stimmt, an std::function hab ich gar nicht gedacht.
Schlechteres Beispiel:
boost::any
-- nicht weil die Klasse nicht gut entwickelt ist, sondern weil Leute sie einsetzen ohne sie zu benötigen.
Was nicht gut ist, ist explizite Fallunterscheidung (switch, if-else, RTTI). Gut ist Polymorphie.Das Beispiel hatte ich im Sinn als ich schlechte Anwendung meinte.