Functionsaufruf wenn Member in Klasse geändert



  • Und falls das von Helium jetzt noch nicht ganz klar ist:

    template<class T>
    class clalling_proxy
    {
    private:
        T safed;
        vector<void(*)()> callbacks;
    public:
        const calling_proxy& operator=(T& t)
        {
            safed=t;
            call_all_callbacks();
        };
        void add_callback(void(*pf)())
        {
            callbacks.push_back(pf);
        };
        void remove_callback(void(*pf)())
        {
            callbacks.erase(pf);    //geht das?
        };
        void call_all_callbacks()
        {
            for(unsigned i=0;i<callbacks.size();++i)
                callbacks[i]();
        };
    };
    

    Ist natürlich nach belieben erweiterbar...



  • Danke ness, aber mir ist nicht nur das von helium unklar, sondern deine Vorgabe auch, bzw. weiß ich nicht wie ich das verwenden soll, ich lerne ja noch.
    Templetes sind mir schon bekannt, verstehe ich aber erst noch gering.
    vektor kenn ich überhaupt nicht.

    wie gesagt, ich weiß nicht wie ich dein Beispiel in meiner Klasse für besagten Zweck verwenden soll.



  • Einer_der_Lernt schrieb:

    Danke ness, aber mir ist nicht nur das von helium unklar, sondern deine Vorgabe auch, bzw. weiß ich nicht wie ich das verwenden soll, ich lerne ja noch.

    Wenn du so weit bist, dass du das von Helium verstehst und umsetzen kannst, willst du es nicht mehr, weil du dich an die Gegebenheiten gewöhnt hast 😉 Das Beispiel von ness ist eine Art Callback-Registrierung, mit dem was Helium gesagt hat hat das so gut wie nichts zu tun.

    vektor kenn ich überhaupt nicht.

    Solltest du aber, vector ist eine der wichtigsten Klassen der Standardbibliothek.



  • @Bashar
    Deine Hinweise und Komentare in Ehren, aber anstelle mein Vorhaben zu Zerreden, wären Informationen zu meinen Fragen mir lieber. Wenn ich das habe was ich will, auch wenn es zusammen gebastelt ist oder gar ganz kopiert, dann kann ich das ganze besser Zeile für Zeile auseinander nehmen und lernen es zu verstehen, es kommt z.B. vector, oerator= (operator++.-- etc.) usw. vor, die ich somit besser erlernen kann, da ich weiß was das Endergebnis ist.

    Ich versuche mal den code von ness zu entschlüsseln, in wie weit ich es verstehe:

    template<class T> 
    /* wo folgend ein T steht, wird mit dem Klassennamen ersetzt, auch bei vererbung */
    class calling_proxy 
    { 
    private: 
        T safed; /* wäre dann calling_proxy safed; */
        vector<void(*)()> callbacks;
        /* vector ist eine Art dynamisches Array, <void(*)()> speichert Functionszeiger */ 
    public: 
        const calling_proxy& operator=(T& t) 
        { 
            safed=t; 
            call_all_callbacks(); 
        }; 
        /* wie die operator= function aufgerufen wird weiß ich nicht */
        /* ich denke aber mal T->wert() = 5; (void wert() { ... } ist es nicht */
        void add_callback(void(*pf)()) 
        { 
            callbacks.push_back(pf); 
        }; 
        void remove_callback(void(*pf)()) 
        { 
            callbacks.erase(pf);    //geht das? 
        };
        /* die oberen setzten und entfernen Zeiger aus dem vector */ 
        void call_all_callbacks() 
        { 
            for(unsigned i=0;i<callbacks.size();++i) 
                callbacks[i](); 
        };
        /* der aufruf von operator=, hier werden alle Functionen die im vector sind aufgerufen */ 
    };
    

    wie ich das jetzt aber nutze damit eine Function aufgerufen wird, wenn der Member int wert; geändert wird, weiß ich nicht.



  • Sag mal, was spricht eigentlich genau dagegen, daß Du alle Änderungen an der Variable über setVariable(parameter) vornimmst und dort auch Deinen Benachrichtigungsaufruf unterbringst? Alles andere ist irgendwie hacky und genau darauf versucht Bashar Dich aufmerksam zu machen. Gerade weil Du noch einiges zu lernen hast ist es nicht sinnvoll eine Lösung zu verstehen zu versuchen die man nicht verwenden sollte.

    MfG Jester



  • @Jester
    es spricht nichts dagegen, ich verwendete bisher in allen lernprojekten get_variable() und set_variable(x), mit anderen Worten, es ist mir bekannt.
    Meine suche war jetzt nach der Möglichkeit wie es Borland bietet, und es giebt diese Möglichkeit, also möchte ich diese gerne erlernen, wie man sieht ist es nicht einfach und es kommen dinge drinn vor die gleich mit erlene.
    Sollte die Nutzung der Möglichkeit nicht Ratsam sein, kann es sein das ich das dann auch nicht nutze, aber ich weiß wie es geht und das gelernte kann ich sicherlich für andere Zwecke mal gebrauchen.

    zum Topic:
    Ich habe das mal umgeschrieben um das mit template und operator= besser zu verstehen, mit vector taste ich mich dann langsam ran:

    #include <windows.h>
    #include <vector>
    
    using namespace std;
    
    template<class T> 
    class _property 
    { 
    private: 
        T safed; 
    public: 
        const _property& operator=(T t) 
        { 
            safed=t; 
        }; 
        /* ist folgendes der umgekehrte weg??? */
        T operator=(_property&)
        {
            return safed;
        } 
    }; 
    
    class teste {
        public:
            _property<int> wert; 
    
    };
    //.............
    teste *test = new teste();
    test->wert = 5;
    

    Das Funktioniert auf jeden Fall, aber
    int x = test->wert;
    geht nicht (kein convert von _property<int> nach int),
    ist der umgekehrte weg von mir richtig?



  • Warum hat mein Vorschlag mit dem was Helium sagt nix zu tun? Das ist doch n proxy mit überladenem operator=. Nur, wenn ich das Problem richtig verstanden habe, geht es doch darum Funktionen aufzurufen wenn der Wert geändert wird. Nur hat das wenig Sinn, wenn man so eine Funktion nicht registrieren kann... Wenn es nur um eine Funktion geht kann man die auch als template-parameter Verwenden, oder man benutzt Funktoren und interne Klassen, aber das sind alles Varianten. Hab ich da was komplett falsch verstanden?

    Zur benutzung: (find ich auch doof, aber egal...)

    class test
    {
    public:
        calling_proxy<int> wert;
    };
    
    void mach_was()
    
    test.wert.add_callback(mach_was);
    test.wert=4;    //der überladene operator= wird mit vier aufgerufen
    //mach_was() wird aufgerufen
    

    So stell ich mir das jedenfalls vor...



  • So, ich habe in den letzten Stunden viel über template und operator überladung gelesen, ja toll schöne Sache, sicherlich mal zu gebarauchen, ich habe auch viel damit rum experimentiert. ABER
    Nicht das was ich meine, ich kann nur die Operatoren für Klassen überladen, so habe ich Variablen die einer Klasse entsprechen:

    klasse a = test->b;
    

    was ich aber möchte, ist ein Event, also Functionsaufruf wenn eine Variable geändert wird, nicht eine Klasse!
    damit folgendes funktioniert:

    /* 1 */ int a = 7;
    /* 2 */ test->wert = a;                  //event - Function aufrufen
    /* 3 */ int b = test->wert;              // ebenso
    /* 4 */ if (test->wert == b) /* etc. */  // hier auch (ist ja wie 3)
    

    Klasse nach int casten geht nicht, und soll auch nicht der Sinn sein

    - @helium, wenn deine Angabe dem entspricht mit Proxy, wie muß ich das dann machen.
    - sollte functor etc. die einfachere Methode sein: was ist das, wie benutze ich sowas?
    - wie kann ich nun das genau realisieren?

    @Bashar und Jester
    wenn ihr wisst wie ich das realisieren kann, bitte ich euch mir zu helfen.
    Das mag zwar nicht so toll sein, aber ich lerne immer mehr, wer hätte gedacht das ich heute Überladung und template lerne.
    Danke

    PS: <vector> ist wirklich nützlich und cool, beschäftige mich gerade nebenbei damit, <map> gefällt mir aber für manch viele Testprog. von mir am besten, bin durch vector drauf gekommen und guck mir beides genauer an.



  • Man kann per se keinen Code aufrufen lassen, wenn eine Variable eines Basistyps (int, etc.) geaendert wird. Ginge schon, bloss gibt's keinen Compiler dafuer, und keine C++ Spracherweiterung, die das unterstuetzen wuerde.

    Du kannst aber folgendes machen:

    #include <string>
    
    #include <stdio.h>
    
    typedef std::string String;
    
    template < class T >
    class MutiVar {
       public:
       typedef void (*CallbackHook)( MutiVar<T>& var );
       T            obj;
       String       id;
       CallbackHook func;
       MutiVar( const String& _id, CallbackHook _func )
          :   id(_id), func(_func) { } 
       // ...
       MutiVar<T>& operator=( const T& value ) {
          obj = value;
          func( *this );
       }
       // ...
    };
    // ...
    void Y_Callback( MutiVar<int>& var ) {
       printf( "variable %s has been modified to %d\n", var.id.c_str(), var.obj );
    }
    
    void func( void ) {
       MutiVar<int>  a( "Variable A", Y_Callback );
       a = 5;
    }
    

    In einer Klasse musst Du die Initialisierung der Variable natuerlich im Konstruktor machen.

    class F {
       MutiVar<int> a;
       F( void );
    };
    
    F::F( void ) : a( "Variable A" ), Y_Callback ) { }
    

    So geht's auf jeden Fall ohne groesseren Aufwand.

    Auch wenn's nicht das ist, was Du haben wolltest! 😉



  • Sooooo Freunde,

    ich habe jetzt viel gelernt und meine eigenen Datenvariablen (class) gebastelt, funktioniert super, aber wie Bashar und Jester schon sagten, ist das nicht das tolle und ware und man sollte es auf der traditionalen Art machen, ala Getter und Setter (get_xxx(), set_xxx(value) ), doch ich brauche Ordnung, und für Windows mit seinen Controls verliert man schnell den Überblick, wenn die Eingabehilfe, bzw. Ergänzung z.B. bei der dev-cpp IDE, aufklappt.
    Daher das ganze hier. Ich habe mir zu diesem Zweck was anderes einfallen lassen, eine Get Klasse und eine Set Klasse, so das ich alle getter in einer Klasse habe und alle Setter in einer Klasse:
    ControlKlasse->Get->Width(), ControlKlasse->Set->Width(123)
    Funktioniert auch super, hier mal eine Kurzform aus der Testphase:

    #include <windows.h>
    
    #define MYWINMOVE 77701
    #define MYSETTEXT 77702
    #define MYSETMENU 77703
    #define MYSETICON 77704
    /* u.s.w. etc. */
    
    class parameter {
        public:
            HWND Handle;
            int Width;
            int Height;
            int Left;
            int Top;
            LPCSTR Caption;        
            void UpdateControll(int type) {
                if (type == MYWINMOVE && Handle) MoveWindow(Handle,Left,Top,Width,Height,true);
                /* u.s.w. etc. */
            }    
    
    };
    
    class getparam {
        private:
            parameter* param;
        public:
            getparam(parameter* p) {param = p;}
            ~getparam() {}
            int Width() {return param->Width;}
    };
    
    class setparam {
        private:
            parameter* param;
        public:
            setparam(parameter* p) {param = p;}
            ~setparam() {}
            void Width(int width) {
                param->Width = width;
                param->UpdateControll(MYWINMOVE);
            }
    };
    
    class test {
        private:
            parameter* param;
        public:
            getparam* Get;
            setparam* Set;
            test() {
                param = new parameter();
                Get = new getparam(param);
                Set = new setparam(param);
                /* param->Handle = CreateWindow(....... */
            }
            ~test() {
                delete param;
                delete Get;
                delete Set;
            }
    
    };            
    //.............
    // in WinMain:
    test* t = new test();
    t->Set->Width(5);
    int x = t->Get->Width();
    if (x == 5) MessageBox(NULL,"ok 5","info",MB_OK);
    t->Set->Width(8);
    x = t->Get->Width();
    if (x == 8) MessageBox(NULL,"ok 8","info",MB_OK);
    // Test alles ok
    

    Was halltet ihr davon?



  • enno-tyrant schrieb:

    [code]
    int eingabe;
    cout << "Wert eingeben: ";
    cin >> eingabe;
    test2.(eingabe);
    

    Hmm, was für eine Syntax ist denn das? Ist damit ein impliziter Konstruktoraufruf gemeint und der Punkt nur versehentlich reingerutscht?


Anmelden zum Antworten