Object und Callback

OP #2505346
Lesenswert?

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
OP #2505371
Lesenswert?

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)
#2505372
Lesenswert?

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 #2505376
Lesenswert?

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?
#2505381
Lesenswert?

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.
#2505418
Lesenswert?

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
#2505455
Lesenswert?

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 #2505560
Lesenswert?

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

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren