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_BINARY

    und Abarten von diesen drei:
    REG_MULTI_SZ
    REG_EXPAND_SZ

    so 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.


Anmelden zum Antworten