Herzlich Willkommen, lieber Gast!
  Sie befinden sich hier:

  Forum » C / C++ (ANSI-Standard) » Callback-funktionen

Forum | Hilfe | Team | Links | Impressum | > Suche < | Mitglieder | Registrieren | Einloggen
  Quicklinks: MSDN-Online || STL || clib Reference Grundlagen || Literatur || E-Books || Zubehör || > F.A.Q. < || Downloads   

Autor Thread - Seiten: > 1 <
000
21.08.2003, 09:57 Uhr
~Oliver
Gast


Hallo Forum,

ich habe zwei Klassen A und B, wobei Klasse A Klasse B kennt, aber nicht umgekehrt. Nun möchte ich einen Callback von Klasse B zu Klasse A machen.

Einen Funktionspointer und Methoden zum Setzen der Callback-Funktion habe ich bereits:

Klasse A, Header:

C++:
extern B MyB; // wird in der ausführenden Unit definiert

class A
{
  public:
    void AufrufSetzeCallback(); // Callback-Funktion wird auf MyIntegerFunktion gesetzt
    int MyIntegerFunktion(int InInt); // Hierauf soll die CB-Funktion verweisen

};



Klasse A, Quelltext:

C++:
int A::MyIntegerFunktion(int InInt)
{
  return (InInt*InInt);
}

void A::AufrufSetzeCallback()
{
  MyB.SetzeCallbackFunktion(&A::MyIntegerFunktion);
}



Klasse B, Header:

C++:
class A;

class B
{
  public:
    int (A::*CallbackFunktion)(int);
    void SetzeCallbackFunktion(int (A::*InFunktion)(int)); // CB-Funktion wird auf InFunktion gesetzt
};



Klasse B, Quelltext:

C++:
void B::SetzeCallbackFunktion(int (A::*InFunktion)(int))
{
  this->CallbackFunktion = InFunktion;
}



Entscheidend ist, dass der Funktionspointer in Klasse B als A::*CallbackFunktion deklariert ist (und wohl auch so deklariert werden muss). Wenn ich aber jetzt den Callback vollziehen und in Klasse B den Funktionspointer aufrufen will, wie muss ich den denn dann aufrufen? Schreibe ich "MyB.CallbackFunktion(IntegerZahl)" erhalte ich die Meldung, das sei keine Funktion. Vielen Dank für Antworten.

CPP tag added by virtual

Dieser Post wurde am 21.08.2003 um 10:29 Uhr von virtual editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
001
21.08.2003, 10:55 Uhr
virtual
Sexiest Bit alive
(Operator)


Ich bin der Meinung, daß es so wie geschildert garnicht gehen kann, weil dieses Ding hier:

C++:
int (A::*InFunktion)(int)


Nur einen Typen definiert, nicht jedoch eine Variable. Also muß

C++:
this->CallbackFunktion = InFunktion


schon nicht gehen. Sinnvoll ist es also schonmal, ein Typedef für den Callback einzuführen:

C++:
typedef int (A::*callback_t)(int);


Ein Callback kann also so in einer Variablen speichert werden:

C++:
callback_t cb = &A::deineMethode(int);


Darauf basierend könnte man zB schreiben:

C++:
#include <iostream>

class A;
class B;
extern B myB;

typedef  int (A::*callback_t)(int);

struct A
{
    void setCallback();
    int theCallback(int a) { return a*a; };
};

class B
{
    callback_t cb;
public:
    void setCallback(callback_t cb) { this->cb = cb; }
    int callCallback(A& a, int x) { return (a.*cb)(x); }
} ;


void A::setCallback()
{
    myB.setCallback(&A::theCallback);
}


B myB;

int main()
{
    A a;
    a.setCallback();
    std::cout<<myB.callCallback(a, 4711)<<std::endl;
}



Wobei ich neben der Verwendung der gloablen Variablen noch weitere Zweifel an einem solchen Design hätte. Aber Du müsstest schon mehr sagen, was die Aufgabe ist, um da was genaues zu zusagen.
--
Gruß, virtual
Quote of the Month
Ich eß' nur was ein Gesicht hat (Creme 21)

Dieser Post wurde am 21.08.2003 um 10:57 Uhr von virtual editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
002
21.08.2003, 11:27 Uhr
~Oliver
Gast


Das scheint tatsächlich zu funktionieren. Das entscheidende ist wohl - neben der Typdefinition -, den Funktionszeiger in Klasse B als Methode von B zu rufen.

Die Anwendung von dem ganzen:
Ein TCP-Client soll empfangene Daten an eine übergeordnete Klasse zur weiteren Verarbeitung geben.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
003
21.08.2003, 11:35 Uhr
virtual
Sexiest Bit alive
(Operator)


Es wird aber als Methode von A aufgerufen.
--
Gruß, virtual
Quote of the Month
Ich eß' nur was ein Gesicht hat (Creme 21)
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
004
21.08.2003, 13:09 Uhr
~Oliver
Gast


Genau das meinte ich.

Aber so ganz geht es noch nicht.
Ich möchte schon gern die Klassen A und B in verschiedene Units packen. Im Header der Unit von Klasse A includiere ich den Header von Klasse B, im Header der Unit von Klasse B gebe ich mit "class A" Klasse A bekannt. Wenn ich aber in callCallback zum Aufruf (a.*cb)(x) komme, erhalte ich eine Zugriffsverletzung.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
005
21.08.2003, 13:16 Uhr
virtual
Sexiest Bit alive
(Operator)


Wen Du eine Zugriffsverletzung bekommst, dann passiert das ja zur Runtime und nicht zur Compiletime. Von daher glaube ich nicht, daß das Problem unmittelbar mit der Verteilung der Header /Units zu tun hat, weil sonst der Compiler gemuckt hätte.
--
Gruß, virtual
Quote of the Month
Ich eß' nur was ein Gesicht hat (Creme 21)
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
006
21.08.2003, 14:32 Uhr
~Oliver
Gast


Der Fehler tritt beim Setzen der Callback-Funktion auf. Sobald B.setCallback in Richtung A.setCallback verlassen wird, ist myB.cb wieder NULL. Wenn ich myB als Membervariable der Klasse A verwende, habe ich dieses Problem allerdings nicht, schreibe ich alles in einer Unit auch nicht.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
007
21.08.2003, 14:40 Uhr
virtual
Sexiest Bit alive
(Operator)


Sieht so aus, als hättest Du zwei myB. Irgendwo ein extern vergessen? Eigentlich auch egal: der Feinere Weg wäre ja sowas hier:


C++:
/* Header a.h */

class B;
struct A
{
    static B* pmyB;
    static void setMyB(B* pb) { pmyB= pb; };
    
    void setCallback() { pmyB->setCallback(&A::theCallback); }
}


Wodurch du das globale B eindeutig der Klasse A zuordnen kannst.
--
Gruß, virtual
Quote of the Month
Ich eß' nur was ein Gesicht hat (Creme 21)
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
008
22.08.2003, 08:19 Uhr
~Oliver
Gast


B ist ein Datenmodul. Ist da eine Deklaration wie static B* pmyB überhaupt möglich?
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
009
22.08.2003, 10:14 Uhr
virtual
Sexiest Bit alive
(Operator)


Ja, ist möglich.
--
Gruß, virtual
Quote of the Month
Ich eß' nur was ein Gesicht hat (Creme 21)
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
Seiten: > 1 <     [ C / C++ (ANSI-Standard) ]  


ThWBoard 2.73 FloSoft-Edition
© by Paul Baecher & Felix Gonschorek (www.thwboard.de)

Anpassungen des Forums
© by Flo-Soft (www.flo-soft.de)

Sie sind Besucher: