Member-Funktionspointer übergeben



  • Hallo,

    ich stehe offenbar mal wieder völlig auf der Leitung.
    Ich möchte in meinem SDI-Progrämmchen eine Box mit Buttons und Slidern anzeigen.
    Dazu habe ich eine Klasse CKameraSteuerung von CStatic abgeleitet. In dieser Klasse möchte ich dann die Slider, Buttons und EditControls schon einmal Auswerten und validieren bevor es zurück zum Hauptprogramm geht. Eine Instanz von CKameraSteuerung ist Member von CKameraView. Das Anzeigen "auf" der Dokumentanzeige und die intere Auswertung in CKameraSteuerung geht auch schonmal.

    Und nun möchte ich gerne in der View-Klasse eine Callback-Memberfunktion
    void KameraCtrlChgd() haben, die aufgerufen wird, wenn CKameraSteuerung Sliderverschiebungen, Edits usw. ausgewertet hat.

    Der Plan ist es, dass das View-Objekt beim Initialisieren der einen Instanz von CKameraSteuerung einen Funktionspointer auf seine Callback-Memberfunktion und einen this-pointer übergibt. Und damit soll aus CKameraSteuerung die Memeberfunktion des Views aufgerufen werden.

    Ich bekomme es schon nicht richtig deklariert und syntaktisch gibt es da auch noch Schwachstellen. Ich tue mich auch noch schwer damit wo der Typ aufhört und der Bezeichner anfängt.

    View.h:

    #include "KameraSteuerung.h"  //schon unschön an dieser Stelle, aber wie CKameraSteuerung zum Member machen
    class CKameraView :public CScrollView
    {
    ....
    public:
        void KameraCtrlChgd();
    private:
        CKameraSteuerung* KameraSteuer;
    }
    

    View.cpp:

    CKameraView::OnInitialUpdate()
    {....
    KameraSteuer = new CKameraSteuerung();
    KameraSteuer->Create(...) //Methode aus CStatic;
    KameraSteuer->Aktivieren(&CKameraView::KameraCtrlChgd,this)  //hier geht es schon los
    // KameraSteuer->Aktivieren(&KamerCtrlChgd,this); // MemberFunktionszeiger ohne Klasse
    

    Da das hier schon nicht kompilierbar und deswegen macht der Rest auch keinen Sinn.

    KameraSterung.h

    class CKameraSteuerung : public CStatic
    {
        void Aktivieren( void(*RueckRuf)() ,void* );
        void BescheidSagen ();
    private:
        void (CKameraView::*pFunkt)(); //
        void* pElternFenster;   // eigentlich ein Zeiger auf ein CKameraView-Objekt
    };
    

    KameraSteuerung.cpp

    void CKameraSteuerung::Aktivieren(void (*RueckRuf)(),void* pParent){
    ...
        pFunkt=RueckRuf;
        pElternFenster=pParent;
    }
    void CKameraSteuerung::BescheidSagen(){
        pElternFenster->pFunkt();    //so ist es gemeint. Geht aber leider so nicht
    

  • Mod

    Nimm doch ein einfaches Interface und leite die View Klasse auch von diesem Interface ab., Dann musst Du der Kameraklasse nur noch den Zeiger auf dieses Interface geben.



  • Mal ohne den Sinn zu hinterfragen ...

    Laser-Axel schrieb:

    #include "KameraSteuerung.h"  //schon unschön an dieser Stelle, aber wie CKameraSteuerung zum Member machen
    class CKameraView :public CScrollView
    {
    ....
    public:
        void KameraCtrlChgd();
    private:
        CKameraSteuerung* KameraSteuer;
    }
    

    Das Include brauchst du nicht. Wenn du nur einen Zeiger auf CKameraSteuerung brauchst, genügt es, die Klasse zu deklarieren ("Vorwärtsdeklaration"):

    class CKameraSteuerung;
    

    View.cpp:

    CKameraView::OnInitialUpdate()
    {....
    KameraSteuer = new CKameraSteuerung();
    KameraSteuer->Create(...) //Methode aus CStatic;
    KameraSteuer->Aktivieren(&CKameraView::KameraCtrlChgd,this)  //hier geht es schon los
    // KameraSteuer->Aktivieren(&KamerCtrlChgd,this); // MemberFunktionszeiger ohne Klasse
    

    Da das hier schon nicht kompilierbar und deswegen macht der Rest auch keinen Sinn.

    KameraSterung.h

    class CKameraSteuerung : public CStatic
    {
        void Aktivieren( void(*RueckRuf)() ,void* );
        void BescheidSagen ();
    private:
        void (CKameraView::*pFunkt)(); //
        void* pElternFenster;   // eigentlich ein Zeiger auf ein CKameraView-Objekt
    };
    

    Warum void*? Füge eine Deklaration von CKameraView ein und deklariere pElternFenster aus Zeiger darauf.

    KameraSteuerung.cpp

    void CKameraSteuerung::Aktivieren(void (*RueckRuf)(),void* pParent){
    ...
        pFunkt=RueckRuf;
        pElternFenster=pParent;
    }
    void CKameraSteuerung::BescheidSagen(){
        pElternFenster->pFunkt();    //so ist es gemeint. Geht aber leider so nicht
    
    void CKameraSteuerung::Aktivieren(void (CKameraView::* Rueckruf)(), ...) {
      ...
      (pElternFenster->*Rueckruf)();
    }
    

    (etwas vereinfacht, ich hoffe die Idee kommt rüber. Die Klammern müssen sein, weil ->* eine ziemlich niedrige Priorität hat.)



  • Bashar schrieb:

    Mal ohne den Sinn zu hinterfragen ...
    Das Include brauchst du nicht. Wenn du nur einen Zeiger auf CKameraSteuerung brauchst, genügt es, die Klasse zu deklarieren ("Vorwärtsdeklaration"):

    Ich dachte eigentlich ich hätte den Sinn des ganzen einigermaßen erläutert... Mit Vorausdeklaration geht schonmal das sauberer.

    View.cpp:

    CKameraView::OnInitialUpdate()
    {....
    KameraSteuer = new CKameraSteuerung();
    KameraSteuer->Create(...) //Methode aus CStatic;
    KameraSteuer->Aktivieren(&CKameraView::KameraCtrlChgd,this)  //Aufruf geht nicht
    

    Der Aufruf funktioniert leider nicht.
    Die entsprechende compilermeldung lautet: error C2664: 'void CKameraSteuerung::Aktivieren(void *(__cdecl *)(void),CKameraView )': Konvertierung des Parameters 1 von 'void (__thiscall CKameraView:: )(void)' in 'void *(__cdecl *)(void)' nicht möglich

    Ich bräuchte da nochmal einen Tip wie Aufruf, Deklaration und Funktionskopf auszusehen haben. Ich seh schon doppelte Doppelpunkte und Sternchen, wenn ich die Augen schließe 🙂

    KameraSterung.h

    class CReis_KameraView;
    
    class CKameraSteuerung : public CStatic
    {
        void Aktivieren( void (*RueckRuf()) ,CReis_KameraView* );
        void BescheidSagen ();
    private:
        void (CKameraView::*pFunkt)(); //
        CKameraView* pElternFenster;   // Zeiger auf ein CKameraView-Objekt mit vorausdeklaration auch zumindest "Intellisens-konform"
    };
    

    KameraSteuerung.cpp

    void CKameraSteuerung::Aktivieren(void (*RueckRuf)(),void* pParent){
    ...
        pFunkt=RueckRuf;
        pElternFenster=pParent;
    }
    void CKameraSteuerung::BescheidSagen(){
        (pElternFenster->*pFunkt)();    //  Geht aber leider so nicht
    

    Das sollten erstmal zwei Memberfunktionen bleiben. Die Memberfunktion Aktivieren() soll nicht sofort wieder die Memberfunktion im Elternfenster aufrufen, sonder tut das erst viel später wenn an den Steuerelementen bedient wurde. Deswegen müsste ich den Funktionspoiter zwischenspeichern.



  • Du hast die geänderte Signatur von Aktivieren (-> mein Posting) nicht übernommen.



  • Ich hab es immernoch nicht zusammen. Mittlerweile habe ich das eigentliche Problem mit message-handler in CKameraView und einem PostMessageW() umschifft. Dennoch würde es mich interessieren wie das mit Funktionspointern funtionieren würde bzw. warum es nicht funktioniert.
    Es gibt eine Zugriffsverletzung beim Aufruf der Callback Funktion.

    Kamerasteuerung.h

    ....
    void Aktivieren( void (CKameraView::*) () ,CKameraView* );
    void (CReis_KameraView::*pFunkt)(); // zwischenspeichern um es später aufrufen zu können
    CReis_KameraView* pElternFenster;
    

    Kamerasteuerung.cpp:

    void CKameraSteuerung::Aktivieren(void (CKameraView::* Rueckruf)(), CKameraView* pParent){
    ...
    if ((Rueckruf != NULL) && (pParent != NULL)){
    	pFunkt=Rueckruf;
    	pElternFenster=pParent;
    //testweise direkt hier den Aufruf der Callback funktion. Sinn macht es erst an anderer Stelle
    	(pElternFenster->*pFunkt)(); // Scheppert mit Zugriffsverletzung
    } 
    }
    

    KameraView.cpp:

    void CReis_KameraView::OnInitialUpdate()
    {
    ...
        KameraSteuer->Aktivieren(&CKameraView::KameraCallBack,this); //von hier kommt der Aufruf
    }
    


  • Wie ist die Beziehung zwischen CKameraView und CReis_KameraView?



  • CKameraView hat eine Membervariable die einen Pointer auf eine eine Instanz von CKameraSteuerung hält.
    CKameraView.h:

    class CReis_KameraView : public CScrollView
    {...
    CKameraSteuerung* KameraSteuer;
    ...}
    

    KameraSteuer wird mit "KameraSteuer = new CKameraSteuerung();" in ONInitialUpdate()erzeugt.

    Sonst erbt CKameraSteuerung von CStatic
    KameraSteuerung.h

    class CKameraSteuerung : public CStatic
    

    CKameraView erbt von CScrollView.



  • Das war nicht die Frage.


Log in to reply