Variablen mit Callback



  • Hallo,

    ich bin auf der Suche nach einer Methode, diese get/set Funktionen in Klassen zu vermeiden, weil die doch ziemlich laestig sind. Andererseits moechte ich schon, dass Variablen nicht ohne Wissen der Klasse einfach geaendert werden koennen.

    Mein Ansatz war nun folgender:

    template <typename T, typename U>
    class CBMember;
    
    template <typename T, typename U>
    std::ostream& operator<< (std::ostream& os, const CBMember<T, U>& cb);
    
    template <typename T, typename U>
    class CBMember
    {
    public:
        CBMember ();
    
        void init (U* parent, T (U::*cbFunc)(const T& value));
    
        T& operator= (const T& value);
        T operator() () const;
    
        friend std::ostream& operator<< <> (std::ostream& os, const CBMember<T, U>& cb);
    
    private:
        U* _parent;
        T (U::*_cbFunc)(const T& value);
    
        T member;
    };
    
    template <typename T, typename U>
    CBMember<T, U>::CBMember () : _parent(0), _cbFunc(0)
    {
    }
    
    template <typename T, typename U>
    void CBMember<T, U>::init (U* parent, T (U::*cbFunc)(const T& value))
    {
        _parent = parent;
        _cbFunc = cbFunc;
    }
    
    template <typename T, typename U>
    T& CBMember<T, U>::operator= (const T& value)
    {
        if (_parent && _cbFunc)
            member = (_parent->*_cbFunc)(value);
        else
            member = value;
    
        return member;
    }
    
    template <typename T, typename U>
    T CBMember<T, U>::operator() () const
    {
        return member;
    }
    
    template <typename T, typename U>
    std::ostream& operator<< (std::ostream& os, const CBMember<T, U>& cb)
    {
        os << cb.member;
    
        return os;
    }
    
    class A
    {
    public:
        typedef CBMember<int, A> CBint;
    
        A ();
    
        CBint x;
        int xCBFunc (const int& newx);
    };
    
    A::A ()
    {
        x.init(this, &A::xcb);
    }
    
    int A::xcb (const int& newx)
    {
    // zum Beispiel...
       int tmp;
       std::cout << "Mein x (im Moment " << x << ") wird gerade zu " << newx << " geaendert." << std::endl;
       tmp = newx;
       return tmp;
    }
    

    Ja... funktionieren tut das. Geht das auch irgendwie schoener? Oder ist das generell nicht gut, sowas zu machen?

    Gruesse,
    jehu



  • Ich hab mir auch mal so ein Teil gebastelt, bin aber nicht dazu gekommen, das wirklich ausführlich zu testen. Vielleicht funktionierts ja:

    template <class Var, class C>
    class Property
    {
    public:
    	Property(C& p) : parent(p)
    	{}
    
    	Property(C& p, Var init) : parent(p), var(init)
    	{}
    
    	Var& operator=(const Var& val)
    	{
    		if (parent.PropertyCallback(*this, val, var))
    			var = val;
    	}
    
    	operator Var&()
    	{
    		return var;
    	}
    
    private:
    	Var var;
    	C& parent;
    };
    
    class Test
    {
    	public:
    		Property<int,Test> intProp;
    
    		bool PropertyCallback(Property<int,Test>& prop, int newVal, int oldVal)
    		{
    			std::cout << "Property callback: " << oldVal << " " << newVal << '\n';
    		}
    
    		Test() : intProp(*this, 0)
    		{	}
    };
    
    int main()
    {
    	Test t;
    
    	t.intProp = 1;
    
    	std::cout << t.intProp;
    
    }
    

    Die umfassende Klasse muss nur ein bool PropertyCallback(Property<C,Var>, Var neu, Var alt) haben.


Anmelden zum Antworten