Aufruf einer Klassenmethode



  • Hallo zusammen

    Ich habe eine Klasse Namens KlassseA in C++ definiert. Ebenso habe ich eine Klasse KlasseB definiert. KlasseB enthält ein Array on KlasseA

    #include "KlasseA.h"

    class KlasseA
    {
      void onUpdate(void);
    }
    
    void onUpdate(void)
    {
       rufe DoSomething von KlasseB auf ???? geht das?:)
    }
    
    class KlasseB
    {
       KlasseA Elemente[10];
       void DoSomething(int a, int b);
    }
    

    Ist es möglich, dass ich Klasse A eine Referenz von Klasse B
    z.B. bei der Initialisierung mitgeben kann, damit z.B. die Methode onUpdate in KlasseA DoSomething von KlasseB aufrufen kann?

    Schön wäre da vielleicht eine Event-Prozedur. Ich komme aber leider nicht drauf, wie ich hier vorgehen muss.

    Vielen Dank für Eure Tipps. Ich stehe hier vor einem grossen Wald.

    Geri



  • Dieser Thread wurde von Moderator/in Jochen Kalmbach aus dem Forum C++/CLI mit .NET in das Forum C++ verschoben.

    Im Zweifelsfall bitte auch folgende Hinweise beachten:
    C/C++ Forum :: FAQ - Sonstiges :: Wohin mit meiner Frage?

    Dieses Posting wurde automatisch erzeugt.



  • Erkundige dich mal nach Klassenzeigern (manchmal auch Methodenzeiger genannt).

    Hier ungetestest eine mögliche Lösung:

    class KlasseB; // forward declaration (Vorwärtsdeklaration)
    
    class KlasseA
    {
    public:
      typedef void (KlasseB::*MethodeB)(int a, int b); // selben Parameter wie aufzurufende Methode
    
      KlasseA()
        : m_b(0), m_m(0)
      {
      }
    
      SetB(KlasseB *b, MethodeB m)
      {
         m_b = b;
         m_m = m;
      }
    
      void onUpdate(void);
    
    private:
      KlasseB *m_b;
      MethodeB m_m;
    };
    
    void KlasseA::onUpdate(void)
    {
       if(m_b)
         (m_b->*m_m)(0, 1); // hier Aufruf der übergebenen Methode.
                            // und noch die Parameter anpassen...
    }
    
    class KlasseB
    {
       KlasseA Elemente[10];
    
    public:
       KlasseB();
    
       void DoSomething(int a, int b);
    };
    
    KlasseB::KlasseB()
    {
       // exzemplarisch für ein Element
       Elemente[0].SetB(this, &KlasseB::DoSomething);
    
       Elemente[0].onUpdate();
    }
    


  • Hallo TH

    Super, vielen Dank für das ausführliche Beispiel. Das ist genau das, was ich gesucht habe!

    Inzwischen habe ich das Ganze in ein Progrämmchen gepackt.

    #include "stdafx.h"
    
    class KlasseB; // forward declaration (Vorwärtsdeklaration) 
    
    class KlasseA 
    { 
    public: 
    
      typedef void (KlasseB::*MethodeB)(int a, int b); // selben Parameter wie aufzurufende Methode 
    
      KlasseA() : m_b(0), m_m(0) 
      { 
      } 
    
      void SetB(KlasseB *b, MethodeB m) 
      { 
         m_b = b; 
         m_m = m; 
      } 
    
    	void onUpdate(void); 
    
    	private: 
    		KlasseB *m_b; 
    		MethodeB m_m; 
    
    }
    
    void KlasseA::onUpdate(void) 
    { 
       if(m_b) 
         (m_b->*m_m)(0, 1); // hier Aufruf der übergebenen Methode. 
                            // und noch die Parameter anpassen... 
    
    } 
    class KlasseB 
    { 
       KlasseA Elemente[10]; 
    
    public: 
       KlasseB(); 
    
       void DoSomething(int a, int b); 
    } 
    
    KlasseB::KlasseB() 
    { 
       // exzemplarisch für ein Element 
       Elemente[0].SetB(this, &B::DoSomething);
       Elemente[0].onUpdate(); 
    } 
    
    int _tmain(int argc, _TCHAR* argv[])
    {
    	return 0;
    }
    

    Irgendwie bekomme ich es aber nicht her die Fehler auszumärzen, die mir der Compiler da liefert.

    error C2371: 'KlasseA::onUpdate' : redefinition; different basic types

    error C2533: 'KlasseB::__ctor' : constructors not allowed a return type

    error C2556: 'KlasseA KlasseA::onUpdate(void)' : overloaded function differs only by return type from 'void KlasseA::onUpdate(void)'

    error C2628: 'KlasseA' followed by 'void' is illegal (did you forget a ';'?)
    fatal error C1903: unable to recover from previous error(s); stopping compilation

    Eine Frage aber habe ich noch. Geht das auch, wenn die beiden Klassen in unterschiedlichen Files abgelegt sind?

    Vielen Dank nochmals für Deine Mühe, ich werde mich dann auch melden, wenn es funktioniert

    Habt ihr vielleicht eine Idee an was es liegt. Stehe hier etwas daneben...

    Geri



  • Hallo

    auf jedenfall hast du die Semikolons nach den Klassen vergessen

    class KlasseA
    {
    ...
    };
    

    bis bald
    akari



  • Hi,
    ich habe mal deinen Code ein wenig verändert (schönere Formartierung, fehlende Semikolons nach den Klassendefinitionen hinzugefügt, B::DoSth. durch KlasseB::Dosth. ersetzt etc.), und so geht es...

    class KlasseB;
    typedef void (KlasseB::*MethodeB)(int, int);
    
    class KlasseA
    {
    private:
    	KlasseB *m_b;
    	MethodeB m_m;
    
    public:
    	void SetB(KlasseB *b, MethodeB m)
    	{
    		m_b = b;
    		m_m = m;
    	}
    
        void onUpdate()
    	{
    		if(m_b)
    		{     
    			(m_b->*m_m)(0, 1);
    		} 
    	}
    
    	KlasseA() :
    		m_b(0),
    		m_m(0)
    	{
    	}
    };
    
    class KlasseB
    {
    private:
    	KlasseA Elemente[10];
    
    public:
    	void DoSomething(int a, int b);
    
    	KlasseB()
    	{
    		Elemente[0].SetB(this, &KlasseB::DoSomething);
    		Elemente[0].onUpdate();
    	}
    };
    
    int main()
    {
        return 0;
    }
    

    Anyway, irgendwie hätte ich das anders gemacht 😉



  • Hallo akari

    Hast recht, die Änderung habe ich vorgenommen:) Vielen Dank

    error C2276: '&' : illegal operation on bound member function expression
    error C2653: 'B' : is not a class or namespace name

    Elemente[0].SetB(this, &B::DoSomething);
    
    // heisst es nicht erher:KlasseB?
    
      Elemente[0].SetB(this, &KlasseB::DoSomething);
    

    Beste Grüsse
    Geri



  • Hallo Trundle0x7e

    Super, vielen Dank!!!:) Jetzt war ich etwas zu langsam.

    Du schreibst, du hättest es anderst gemacht. Mich würde deine Varinante wirkliche sehr interessieren. Wäre nett, wenn du mir sie aufzeigst.

    Von einer Webseite habe ich ein Beispiel in C# mit Delegates geladen. Die Funktionsweise ist mir klar, Allerdings ist mein Code in unmanaged C++ geschrieben und ich weiss nicht ob man es auf diese Weise auch lösen könnte.

    Wen es interessiert: http://thesource.ofallevil.com/germany/msdn/library/net/Delegates.mspx?mfr=true

    Beste Grüsse und nochmals vielen Dank

    Geri



  • Hallo,

    ich nochmals.

    int _tmain(int argc, _TCHAR* argv[])
    {
    	KlasseA CA;
    	KlasseB CB;
    
    	CA.SetB(&CB,&CB.DoSomething);  //???
    	CA.onUpdate();
    	while (1==1)
    	{
    	}
    	return 0;
    }
    

    Irgendwie gefällt dem Compiler Zeile 6 noch nicht. Habe schon verschiedene Varinaten probiert:)

    error C2276: '&' : illegal operation on bound member function expression

    Kann mir bitte einer sagen, woran es liegt? ..ich weiss.. u.a. auch an mir:)

    Beste Grüsse
    Geri



  • statt . :: 😉



  • Hallo und vielen Dank für Deine rasche Rückmeldung

    Das habe ich auch versucht, erhalte aber mit:

    CA.SetB(&CB,&CB::DoSomething); //???

    error C2510: 'CB' : left of '::' must be a class/struct/union
    error C2065: 'DoSomething' : undeclared identifier

    Beste Grüsse
    Geri



  • KlasseB::DoSth 😉



  • WOW!!! Super, vielen Dank!!! Ihr seid Spitze 👍 👍

    Nun würden mich nur noch interessiere wie du dieses Problem gelöst hättest:)?

    Beste Grüsse und nochmals vielen Dank für die rasche Hilfe

    Geri



  • Wenn du willst, dass eine bestimmte Methode bei einer bestimmten Klasseninitalisierung aufgerufen wird, hätte ich das einfach so gemacht...

    #include <sstream>
    #include <string>
    #include <iostream>
    #include <vector>
    using namespace std;
    
    class CClassB;
    
    class CClassA
    {
    	friend CClassB;
    
    private:
    	void OnInitByB(const string& sArgument)
    	{
    		cout << __FUNCTION__ << " sArgument==" << sArgument << endl;
    	}
    };
    
    class CClassB
    {
    private:
    	vector<CClassA*> m_As;
    
    public:
    	~CClassB()
    	{
    		for(vector<CClassA*>::iterator pA=m_As.begin();
    			pA!=m_As.end();
    			pA++)
    		{
    			delete (*pA);
    		}
    	}
    
    	void AddNewA()
    	{
    		stringstream ssArgument;
    		ssArgument << "Das Argument von Instanz Nr. " << m_As.size();
    
    		m_As.push_back(new CClassA());
    		m_As.back()->OnInitByB(ssArgument.str());
    	}
    };
    
    int main()
    {
    	CClassB B;
    	B.AddNewA();
    	B.AddNewA();
    	B.AddNewA();
    	B.AddNewA();
    
        return 0;
    }
    


  • Geri schrieb:

    Von einer Webseite habe ich ein Beispiel in C# mit Delegates geladen. Die Funktionsweise ist mir klar, Allerdings ist mein Code in unmanaged C++ geschrieben und ich weiss nicht ob man es auf diese Weise auch lösen könnte.

    Das ist ev. interessant für Dich: Delegates in unmanaged C++
    oder das oder das
    oder einer der anderen Links, die mein Freund hergibt 😉



  • Hallo zusammen

    @Trundle0x7e: Sehr interessant, vielen Dank, dass du mir Deinen Lösungsweg ausführlich aufgezeigt hast. Das sieht sehr übersichtlich und kurz aus!

    @1310-Logik: Vielen Dank für Deinen Hinweis. Das Thema Delegates interessiert mich wirklich sehr, weil ich glaubh, dass man mit der Technik sehr viele Möglichkeiten hat.

    Beste Grüsse und nochmals vielen Dank für Eure sehr kompetente Hilfestellung

    Geri


Anmelden zum Antworten