Variable in Klasse von ausserhalb abändern?



  • 1. Der:

    ]:~§

    sieht aus, wie ein Taliban. 🙂

    2. Initialisierungsliste:

    ClientVars::ClientVars()
    :
    VarName ( 150 )
    {
    }
    

    3. Macht man das normalerweise mittels Getter/Setter. Siehe Kapselung usw.

    4. Sollte das so gehen. VarName ist ein L-Wert..



  • ^^

    Ich habe mehrere CPP-Quelldateien, und damit mehrere Namespaces/Klassen, die cooperieren 😉

    Nun muss ich biem laden:
    -Einstellungen in variablen ablegen
    -Ein paar andere Informationen ablegen

    In bestimmten situationen:
    -Weitere Informationen ablegen
    -Manche Informationen ändern

    Aber auf genannte Informationen muss ich von allen Dateien aus zugreifen können.
    Info: Natürlich ist der code in der main etwas anders, ich hol mir die Instanz der ClientVars Klasse über eine Singleton-ähnliche Funktion, was auch funktioniert, weil er mir die 150 ja ausgibt, wenn ich das schreiben in die Variable auskommentiere.

    Ist es irgendwie möglich, dass ich mit Settern über parameter angeben kann welche var ich ändere? Also so wie es in PHP so lösbar wäre:

    function SetVar($name, $value)
    {
        global $$name; //Das lässt mich in der Funktion auf die externe Variable zugreifen. Ist in C++ ja vernachlässigbar
        $$name = $value;
    }
    


  • Ist es irgendwie möglich, dass ich mit Settern über parameter angeben kann welche var ich ändere?

    Nein, ist es nicht. C++ ist, nicht wie PHP eine dynamische Sprache. Du musst dir da jeden Setter/Getter speziell für die Variable schreiben. (Ist ja nicht so tratisch, ist schnell geschrieben).



  • dark alex schrieb:

    Ist es irgendwie möglich, dass ich mit Settern über parameter angeben kann welche var ich ändere?

    In etwa, ja, allerdings mit etwas geändertem Design. Was wahrscheinlich sowieso nicht schlecht wäre, wenn du, wie du schreibst, "sehr viele Variablen" in deiner Klasse haben willst.

    class Config
    {
        public:
            int getVar( const std::string& name, int default ) const
            {
                std::map<std::string,int>::const_iterator pos = m_vars.find( name );
                if ( pos == m_vars.end() )
                    return default;
                return pos->second;
            }
    
            void setVar( const std::string& name, int value )
            {
                m_vars[name] = value;
            }
    
        private:
            std::map<std::string,int> m_vars;
    };
    

    Verwendet man manchmal, wenn man Error-Codes oder Einstellungen hat, die man aus einer Datei liest.

    Wird halt nur umständlicher, wenn die Variablen verschiedene Typen haben - es kommt halt auf den konkreten Fall drauf an, ob sich solch eine map sinnvoll einsetzen lässt.



  • Ja, ist aber alles andere als sauber und solltest du besser nicht machen:

    #include <iostream>
    #include <map>
    #include <cassert>
    
    class Foo {
    public:
    	Foo()
    	{
    		AddVar("var1", var1);
    		AddVar("var2", var2);
    		AddVar("var3", var3);
    		AddVar("var4", var4);
    	}
    
    	template <typename T>
    	void Set(const std::string& varname, T value)
    	{
    		assert(vars_[varname] != 0);
    		*reinterpret_cast<T*>(vars_[varname]) = value;
    	}
    
    	template <typename T>
    	T Get(const std::string& varname)
    	{
    		return *reinterpret_cast<T*>(vars_[varname]);
    	}
    private:
    	std::map<std::string, void*> vars_;
    	int var1;
    	double var2;
    	std::string var3;
    	char var4;
    
    	template <typename T>
    	void AddVar(const std::string& name, T& p)
    	{
    		vars_[name] = reinterpret_cast<void*>(&p);
    	}
    };
    
    int main()
    {
    	Foo foo;
    	foo.Set("var1", 42);
    	foo.Set("var2", 13.37);
    	foo.Set<std::string>("var3", "Hallo Welt");
    	foo.Set("var4", '!');
    	std::cout << foo.Get<int>("var1") << "\n"
    	          << foo.Get<double>("var2") << "\n"
    	          << foo.Get<std::string>("var3")
    	          << foo.Get<char>("var4") << std::endl;
    }
    

    (Gibt aber bestimmt noch bessere Möglichkeiten)



  • Badestrand schrieb:

    dark alex schrieb:

    Ist es irgendwie möglich, dass ich mit Settern über parameter angeben kann welche var ich ändere?

    In etwa, ja, allerdings mit etwas geändertem Design. Was wahrscheinlich sowieso nicht schlecht wäre, wenn du, wie du schreibst, "sehr viele Variablen" in deiner Klasse haben willst.

    class Config
    {
        public:
            int getVar( const std::string& name, int default ) const
            {
                std::map<std::string,int>::const_iterator pos = m_vars.find( name );
                if ( pos == m_vars.end() )
                    return default;
                return pos->second;
            }
    
            void setVar( const std::string& name, int value )
            {
                m_vars[name] = value;
            }
    
        private:
            std::map<std::string,int> m_vars;
    };
    

    Verwendet man manchmal, wenn man Error-Codes oder Einstellungen hat, die man aus einer Datei liest.

    Wird halt nur umständlicher, wenn die Variablen verschiedene Typen haben - es kommt halt auf den konkreten Fall drauf an, ob sich solch eine map sinnvoll einsetzen lässt.

    Darauf hätte ich ja auch kommen können 😣 Danke!



  • mist...

    Client.cpp

    void ClientVars::setInt( const std::string& name, int value )
    {
    	m_ints[name] = value;
    	cout << "Setting ClientVar<int> " << name << " to " << value << endl;
    }
    

    Main.cpp

    cout << "testGlobal 150: " << glob.getInt((std::string)"testGlobal",0) << endl;
    	glob.setInt((std::string)"testGlobal",2000);
    	cout << "testGlobal 150->2000: " << glob.getInt((std::string)"testGlobal",0) << endl;
    

    Ausgabe:

    testGlobal 150: 150
    Setting ClientVar<int> testGlobal to 2000
    testGlobal 150->2000: 150
    

    ... lol ... Woran kann das liegen?



  • Die C-Casts würde ich weglassen. Wie sieht denn die getInt-Funktion aus?



  • so:

    int ClientVars::getInt( std::string name, int default )
    {
        std::map<std::string,int>::const_iterator pos = m_ints.find( name );
        if ( pos == m_ints.end() )
            return default;
        return pos->second;
    }
    


  • Zeig mal minimalen aber kompilier- und linkfähigen Source. Das hier funktioniert jedenfalls:

    class ClientVars
    {
        // Inhalt wie in Klasse "Config" von ein paar Posts drüber
    }; 
    
    int main()
    {
    	ClientVars x;
    	x.setVar( "Hallo", 123 );
    	std::cout << x.getVar("Hallo",0) << std::endl; // 123
    }
    


  • Bei mir klappt's:

    #include <iostream>
    #include <map>
    #include <string>
    
    using namespace std;
    
    class ClientValues {
    public:
    	void setInt( const std::string& name, int value )
    	{
    		m_ints[name] = value;
    		cout << "Setting ClientVar<int> " << name << " to " << value << endl;
    	}
    	int getInt( std::string name, int defaultV )
    	{
    		std::map<std::string,int>::const_iterator pos = m_ints.find( name );
    		if ( pos == m_ints.end() )
    			return defaultV;
    		return pos->second;
    	}
    private:
    	std::map<std::string, int> m_ints;
    };
    
    int main()
    {
    	ClientValues glob;
    	glob.setInt("testGlobal", 150);
    	std::cout << "testGlobal 150: " << glob.getInt("testGlobal", 0) << std::endl;
    	glob.setInt("testGlobal", 2000);
    	std::cout << "testGlobal 150->2000: " << glob.getInt("testGlobal", 0) << std::endl;
    }
    
    Setting ClientVar<int> testGlobal to 150
    testGlobal 150: 150
    Setting ClientVar<int> testGlobal to 2000
    testGlobal 150->2000: 2000
    

    Sicher dass du den Startwert von 150 auch mit setInt gesetzt hast?



  • dark alex schrieb:

    so:

    int ClientVars::getInt( std::string name, int default )
    

    Das default wird nicht ohne Grund blau formatiert; es ist ein Schlüsselwort der Sprache und kann als solches nicht für Bezeichner verwendet werden.



  • Nexus schrieb:

    kann als solches nicht für Bezeichner verwendet werden.

    Mit dem richtigen Compiler geht alles 🤡


Anmelden zum Antworten