Object und Callback

OP #2505346
Hallo Leute,

ich hab eine Frage.

Ich habe eine Klasse die zweimal instanzier wird.
Diese Klasse hat einen "Callback_Funktionspointer" und eine Funktion.
Nun will ich dass sobald die Callbackunktion aufgerufen wird, die 
Funktion der anderen Instanz aufgeufen wird.

Sozusagen ruft die eine Instanz der klasse die andere instanz der klasse 
auf.

Hier ein kleiner Codeschnipsel der es hoffentlich etwas anschaulicher 
macht! :)
1
class MyClass
2
{
3
  public:
4
    MyClass() {};
5
    void (*Send)( char Daten );
6
    void Receive( char Daten );
7
}
8

9
MyClass* MyObject1, MyObject2;
10

11
int main()
12
{
13
MyObject1 = new MyClass;
14
MyObject2 = new MyClass;
15

16
MyObject1->*Send = &MyObject2->Receive;
17
// Hier möchte ich festlegen dass der CallbackPointer der einen Instanz auf die Funktion der anderen Instanz zeigt.
18

19
MyObject1->Send(0x23);
20
//Hier würde ich hoffen dass die ReceiveFunktion der Instanz2 aufgerufen wird :S
21
}

Leider funktionier das so nicht!
Wäre super wenn jemand einen Rat wüsste!

Grüße Tarkan
Gast
Wenn MyObject1 und MyObject2 wie in deinem Beispiel vom selben Typ sind, 
ist deren send-Funktion sowieso dieselbe (die gibt es nur einmal). Was 
soll dein Ansatz daher einen Sinn haben?

Oliver
OP
Ich habe ein protocol Implementiert dass daten verschlüsslen und einem 
Port übergeben soll (Send_Callback)

auf der "Anderen seite* soll die gleiche Protocolklasse sitzen und daten 
von einem Port entgegen nehmen (receive)

normalerweise laufen die beiden protocol instanzen auf verschiedenen 
maschinen.

aber um die sache zu debuggen möchte ich gerne beide protocol instanzen 
auf dem gleichen pc laufen lassen. und sie sozusagen kurzschließen(ohne 
port, denn man braucht ja keinen innerhalb eines PCs)
Ich versuche das mal einzukreisen...

1. Es gibt Zeiger auf Funktionen, hier egal.

2. Es gibt Zeiger auf Methoden. Das wird hier interessanter.

3. Es gibt Objekte und Zeiger darauf.

4. Ein Zeiger auf eine Methode hat nichts damit zu tun, zu welchem
   Objekt die Methode gehört, sondern zu welcher Klasse.

5. Wenn du eine bestimmte Methode für ein bestimmtes Objekt
   aufrufen musst, dann brauchst du dazu folglich zwei Sachen:
   a) das Objekt oder einen Zeiger darauf
   b) einen Zeiger auf die Methode

Wenn ich jetzt deine Aufgabe richtig verstanden habe, dann willst
du aus dem ersten Objekt die Methode nicht nur aufrufen, sondern
die Methode für das zweite Objekt aufrufen.
Dazu müsstest du also vorher a) das Objekt und b) die Methode
setzen, weil eben die Methode nicht zu einem Objekt gehört.
OP
Klaus Wachtler schrieb:
> Wenn ich jetzt deine Aufgabe richtig verstanden habe, dann willst
> du aus dem ersten Objekt die Methode nicht nur aufrufen, sondern
> die Methode für das zweite Objekt aufrufen.

Exakt !

Klaus Wachtler schrieb:
> Dazu müsstest du also vorher a) das Objekt und b) die Methode
> setzen, weil eben die Methode nicht zu einem Objekt gehört.

Genau. Geht das irgendwie in einem Abwasch?
Gast
welcher Compiler hat denn das übersetzt.
Der (Member-)FunctionsPtr "Send" speichert nur die Adresse von 
"Receive", aber nicht den für den Aufruf notwendigen "this"-Pointer auf 
das andere Objekt.
Tarkan D. schrieb:
> Klaus Wachtler schrieb:
>> Dazu müsstest du also vorher a) das Objekt und b) die Methode
>> setzen, weil eben die Methode nicht zu einem Objekt gehört.
>
> Genau. Geht das irgendwie in einem Abwasch?

Mach doch in die Klasse eine set-Methode, die einen Zeiger auf das 
zweite Objekt und den Zeiger auf die Methode bekommt.
Das merkt sie sich in zwei entsprechenden Menbern.
So etwa sollte es das sein, was du vorhast:
1
#include <iostream>
2
#include <string>
3

4

5
class MyClass
6
{
7
public:
8
    MyClass( const char * werBinIch )
9
        : werBinIch( werBinIch ),
10
          dasAndere( NULL )
11
        {
12
        };
13

14
    void Receive( char Daten )
15
        {
16
            std::cout << "ich bin " << werBinIch << " und bekomme ein " << Daten << std::endl;
17
        }
18

19
    void setDenAnderen( MyClass *p_derAndere, void (MyClass::*p_dieMethodeDesAnderen)( char Daten ) )
20
        {
21
            dasAndere = p_derAndere;
22
            dieMethodeDesAnderen = p_dieMethodeDesAnderen;
23
        }
24

25
    void Send( char Daten )
26
        {
27
            if( dasAndere && dieMethodeDesAnderen )
28
            {
29
                (dasAndere->*dieMethodeDesAnderen)( Daten );
30
            }
31
        }
32

33
private:
34

35
    MyClass    *dasAndere;
36
    void (MyClass::*dieMethodeDesAnderen)( char Daten );
37

38
    std::string   werBinIch;;
39
};
40

41
MyClass  * MyObject1;
42
MyClass  * MyObject2;
43

44
int main()
45
{
46
     MyObject1 = new MyClass( "erster" );
47
     MyObject2 = new MyClass( "zweiter" );
48

49
     MyObject1->setDenAnderen( MyObject2, &MyClass::Receive );
50

51
     MyObject1->Send( 'X' );
52
}

Ausgabe mit Visual C++:
1
ich bin zweiter und bekomme ein X
Eine andere, etwas allgemeinere Methode leitet sich vom Grundsatz ab:

Wenn du ein Problem nicht dingfest machen kannst, dann mach eine Klasse 
draus.


Das funktioniert so:
Anstatt eines Funktionspointers kriegt die Instanz ein Objekt übergeben, 
welches darüber bescheid weiß, welche andere Methode in welchem anderen 
Objekt aufzurufen ist. Der Auslöser der Funktionalität bemüht nicht den 
Funktionspointer um eine Methode in einem anderen Objekt aufzurufen, 
sondern er wendet sich an einen Proxy.

Dazu machen wir einfach mal eine Basisklasse, von der dann später die 
einzelnen konkreten Proxies abgeleitet werden:
1
class Proxy
2
{
3
  public:
4
    virtual ~Proxy() {}
5
    void CallIt( char Daten ) = 0;
6
};

So weit so gut.
Dein MyClass Objekt hält jetzt so einen Proxy und da das ganze Polymorph 
verwendet werden soll, hält es genau genommen einen Pointer (einen 
non-owning Pointer, soll heißen: Ein MyClass Objekt ist nicht für die 
Verwaltung new/delete der Proxies zuständig)
1
class MyClass
2
{
3
  public:
4
    MyClass() : pProxy( NULL ) {};
5

6
    void SetProxy( Proxy* pProxy ) { pProxy_ = pProxy; }
7
    void Receive( char Daten );
8

9
  private:
10
    Proxy* pProxy_;
11
}

Wird, wie gehabt, Receive aufgerufen, so leitet Receive diesen Aufruf 
weiter. Natürlich nur, wenn es überhaupt einen Proxy gibt:
1
void MyClass::Receive( char Daten )
2
{
3
  ....
4

5
  if( pProxy )
6
    pProxy->CallIt( Daten );
7
}

Alles was noch fehlt, ist der konkrete Proxy, der einen CallIt Aufruf an 
ein MyClass Object weitergeben kann, indem er dessen Receive Funktion 
aufruft. Der ist aber schnell gemacht. Auch er bekommt wieder einen 
Pointer auf das Objekt, dessen Receive Methode zuständig ist (und der 
Non-Owning ist)
1
class MyClassProxy : public Proxy
2
{
3
  public:
4
    MyClassProxy( MyClass* pReceiver ) : pReceiver_( pReceiver ) {}
5
    void CallIt( char Daten )   { pRecevier->Receive( Daten ); }
6
}

Damit sind alle Zutaten zusammen und main kann geschrieben werden:
1
int main()
2
{
3
  MyClass MyObject1, MyObject2;
4

5
  MyClassProxy MyProxy( &MyObject2 );   // Der Proxy soll an MyObject2 weitergeben
6
  MyObject1.SetProxy( &MyProxy );       // Und MyObject1 soll den Call über
7
                                        // den Proxy MyProxy weitergeben
8

9
  MyObject1.Receive( 'A' );             // MyObject1 benachrichtigt jetzt
10
                                        // mithilfe des Proxies das Obj MyObject2
11
                                        // das Daten eingetroffen sind.
12
}

Der Vorteil eines Proxies besteht darin, dass MyClass jetzt nicht mehr 
daran gebunden ist, den exakten Typ des aufzurufenden Objektes zu 
kennen. Diese Information steckt im Proxy selber und der kann an die 
jeweilige Situation angepasst werden. Haargenau das gleiche MyClass 
Objekt kann mit einem anderen Proxy dazu gebracht werden, eine Methode 
in einem MyOtherClass Object aufzurufen. Dazu braucht es lediglich einen 
dafür massgeschneiderten Proxy.

Der Nachteil ist natürlich, dass die Aufrufe über den Proxy ein wenig 
langsamer sind, weil ja eine Abstraktionsschicht zwischengeschoben 
wurde. Aber so dramatisch sind die Speed-Unterschiede dann auch wieder 
nicht.
Gast
Oliver schrieb:
> Wenn MyObject1 und MyObject2 wie in deinem Beispiel vom selben Typ sind,
> ist deren send-Funktion sowieso dieselbe (die gibt es nur einmal). Was
> soll dein Ansatz daher einen Sinn haben?

Aber die Objekte sind nicht dieselben! Er möchte offenbar die Objekte 
alös Kommunikationsendpunkte nutzen.

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 14 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.