Rückruffunktion in C ++

Rückruffunktion in C ++

Eine Rückruffunktion ist eine Funktion, die ein Argument, kein Parameter, in einer anderen Funktion ist. Die andere Funktion kann als Hauptfunktion bezeichnet werden. Es sind also zwei Funktionen beteiligt: ​​die Hauptfunktion und die Rückruffunktion selbst. In der Parameterliste der Hauptfunktion ist die Deklaration der Rückruffunktion ohne ihre Definition vorhanden, genau wie Objektdeklarationen ohne Zuweisung vorhanden sind. Die Hauptfunktion wird mit Argumenten aufgerufen (in main ()). Eines der Argumente im Hauptfunktionsaufruf ist die effektive Definition der Rückruffunktion. In C ++ ist dieses Argument ein Hinweis auf die Definition der Rückruffunktion; Es ist nicht die tatsächliche Definition. Die Rückruffunktion selbst wird tatsächlich innerhalb der Definition der Hauptfunktion aufgerufen.

Die grundlegende Rückruffunktion in C ++ garantiert kein asynchrones Verhalten in einem Programm. Asynchrones Verhalten ist der eigentliche Vorteil des Rückruffunktionssystems. Im Asynchronous Callback -Funktionsschema sollte das Ergebnis der Hauptfunktion für das Programm erhalten werden, bevor das Ergebnis der Rückruffunktion erhalten wird. Es ist möglich, dies in C ++ zu tun; C ++ verfügt jedoch über eine Bibliothek namens Future, um das Verhalten des asynchronen Rückruffunktionsschemas zu gewährleisten.

Dieser Artikel erläutert das grundlegende Rückruffunktionsschema. Vieles ist mit reinem C++. In Bezug auf den Rückruf wird auch das grundlegende Verhalten der zukünftigen Bibliothek erklärt. Grundkenntnisse über C ++ und seine Zeiger sind für das Verständnis dieses Artikels notwendig.

Artikelinhalt

  • Grundlegendes Rückruffunktionsschema
  • Synchrones Verhalten mit Rückruffunktion
  • Asynchrones Verhalten mit Rückruffunktion
  • Grundlegende Verwendung der zukünftigen Bibliothek
  • Abschluss

Grundlegendes Rückruffunktionsschema

Ein Rückruffunktionsschema benötigt eine Hauptfunktion und die Rückruffunktion selbst. Die Deklaration der Rückruffunktion ist Teil der Parameterliste der Hauptfunktion. Die Definition der Rückruffunktion ist im Funktionsaufruf der Hauptfunktion angegeben. Die Rückruffunktion wird tatsächlich innerhalb der Definition der Hauptfunktion aufgerufen. Das folgende Programm zeigt dies:

#enthalten
Verwenden von Namespace STD;
int PrincipalFn (char ch [], int (*ptr) (int))

int id1 = 1;
int id2 = 2;
int idr = (*ptr) (id2);
Cout<<"principal function: "<<
ID1<<"<return id1;

int cb (int iden)

Cout<<"callback function"<<'\n';
IDEN zurückgeben;

int main ()

int (*ptr) (int) = &cb;
Char Cha [] = "und";
PrincipalFn (Cha, CB);
Rückkehr 0;

Die Ausgabe ist:

Rückruffunktion
Hauptfunktion: 1 und 2

Die Hauptfunktion wird durch PrincipalFn () identifiziert. Die Rückruffunktion wird durch CB () identifiziert. Die Rückruffunktion wird außerhalb der Hauptfunktion definiert, jedoch tatsächlich innerhalb der Hauptfunktion aufgerufen.

Beachten Sie die Deklaration der Rückruffunktion als Parameter in der Parameterliste der Hauptfunktionserklärung. Die Erklärung der Rückruffunktion lautet "int (*ptr) (int)" ". Beachten Sie den Ausdruck der Rückruffunktion wie ein Funktionsaufruf in der Definition der Hauptfunktion; Jedes Argument für den Anruf für die Rückruffunktion wird dort übergeben. Die Anweisung für diesen Funktionsaufruf lautet:

int idr = (*ptr) (id2);

Wo ID2 ein Argument ist. PTR ist Teil des Parameters, eines Zeigers, der mit der Referenz der Rückruffunktion in der Funktion main () verknüpft wird.

Beachten Sie den Ausdruck:

int (*ptr) (int) = &cb;

In der Funktion main (), die die Erklärung (ohne Definition) der Rückruffunktion mit dem Namen der Definition derselben Rückruffunktion verknüpft.

Die Hauptfunktion wird in der Funktion main () als:

PrincipalFn (Cha, CB);

Wobei Cha eine Zeichenfolge ist und CB der Name der Rückruffunktion ohne seine Argumentation ist.

Synchrones Verhalten der Rückruffunktion

Betrachten Sie das folgende Programm:

#enthalten
Verwenden von Namespace STD;
void Principalfn (void (*ptr) ())

Cout<<"principal function"<<'\n';
(*ptr) ();

void CB ()

Cout<<"callback function"<<'\n';

void fn ()

Cout<<"seen"<<'\n';

int main ()

void (*ptr) () = &cb;
PrincipalFn (CB);
fn ();
Rückkehr 0;

Die Ausgabe ist:

Hauptfunktion
Rückruffunktion
gesehen

Hier gibt es eine neue Funktion. Die ganze neue Funktion besteht darin, die Ausgabe "gesehen" anzuzeigen. In der Funktion main () wird die Hauptfunktion aufgerufen, dann wird die neue Funktion fn () aufgerufen. Die Ausgabe zeigt, dass der Code für die Hauptfunktion ausgeführt wurde, dass für die Rückruffunktion ausgeführt wurde und schließlich die Funktion für die FN () -Funktion ausgeführt wurde. Dies ist ein synchrones (Single-Threaded) -Vor.

Wenn es sich um asynchrones Verhalten handelte, kann das erste Codesegment ausgeführt werden, befolgt stattdessen drei Codesegmente, die in der Reihenfolge aufgerufen werden, bevor das zweite Code -Segment ausgeführt wird.

Nun, die Funktion fn () kann innerhalb der Definition der Hauptfunktion anstelle von innerhalb der Main () -Funktion wie folgt aufgerufen werden:

#enthalten
Verwenden von Namespace STD;
void fn ()

Cout<<"seen"<<'\n';

void Principalfn (void (*ptr) ())

Cout<<"principal function"<<'\n';
fn ();
(*ptr) ();

void CB ()

Cout<<"callback function"<<'\n';

int main ()

void (*ptr) () = &cb;
PrincipalFn (CB);
Rückkehr 0;

Die Ausgabe ist:

Hauptfunktion
gesehen
Rückruffunktion

Dies ist eine Nachahmung des asynchronen Verhaltens. Es ist kein asynchrones Verhalten. Es ist immer noch synchrones Verhalten.

Auch die Reihenfolge der Ausführung des Codesegments der Hauptfunktion und des Codesegments der Rückruffunktion kann in der Definition der Hauptfunktion ausgetauscht werden. Das folgende Programm zeigt dies:

#enthalten
Verwenden von Namespace STD;
void Principalfn (void (*ptr) ())

(*ptr) ();
Cout<<"principal function"<<'\n';

void CB ()

Cout<<"callback function"<<'\n';

void fn ()

Cout<<"seen"<<'\n';

int main ()

void (*ptr) () = &cb;
PrincipalFn (CB);
fn ();
Rückkehr 0;

Die Ausgabe ist jetzt,

Rückruffunktion
Hauptfunktion
gesehen

Dies ist auch eine Nachahmung des asynchronen Verhaltens. Es ist kein asynchrones Verhalten. Es ist immer noch synchrones Verhalten. Wahres asynchrones Verhalten kann wie im nächsten Abschnitt oder mit der Bibliothek, Zukunft erläutert, erhalten werden.

Asynchrones Verhalten mit Rückruffunktion

Der Pseudo-Code für das grundlegende asynchrone Rückruffunktionsschema lautet:

Typausgabe;
Geben Sie CB ein (Typausgabe)

// Aussagen

Typ PrincipalFN (Typeingabe, Typ CB (Typausgabe)))

// Aussagen

Beachten Sie die Positionen der Eingangs- und Ausgabedaten an den verschiedenen Stellen des Pseudo-Code. Die Eingabe der Rückruffunktion ist die Ausgabe. Die Parameter der Hauptfunktion sind der Eingabeparameter für den allgemeinen Code und der Parameter für die Rückruffunktion. Mit diesem Schema kann eine dritte Funktion in der Funktion main () ausgeführt werden (genannt), bevor die Ausgabe der Rückruffunktion gelesen wird (noch in der Funktion main ()). Der folgende Code zeigt dies:

#enthalten
Verwenden von Namespace STD;
char *output;
void cb (char out [])

output = out;

void PrincipalFn (char input [], void (*ptr) (char [50]))

(*ptr) (Eingabe);
Cout<<"principal function"<<'\n';

void fn ()

Cout<<"seen"<<'\n';

int main ()

char input [] = "Rückruffunktion";
void (*ptr) (char []) = &cb;
PrincipalFn (Eingabe, CB);
fn ();
Cout<Rückkehr 0;

Die Programmausgabe lautet:

Hauptfunktion
gesehen
Rückruffunktion

In diesem speziellen Code ist das Ausgaber- und Eingabedatum das gleiche Datum. Das Ergebnis des dritten Funktionsaufrufs in der Funktion main () wurde vor dem Ergebnis der Rückruffunktion angezeigt. Die Rückruffunktion wurde der Variablen, der Ausgabe, so dass das Programm ohne Einmischung fortgesetzt und zugeordnet wurde, um das Ergebnis (Wert) zuzuweisen. In der Funktion main () wurde die Ausgabe der Rückruffunktion verwendet (gelesen und angezeigt), wenn sie benötigt wurde, was zu einem asynchronen Verhalten für das gesamte Schema führte.

Dies ist der einzel-thread-Weg, um ein asynchrones Verhalten von Callback-Funktionen mit reinem C zu erhalten++.

Grundlegende Verwendung der zukünftigen Bibliothek

Die Idee des asynchronen Rückruffunktionsschemas ist, dass die Hauptfunktion zurücksetzt, bevor die Rückruffunktion zurückgibt. Dies geschah im obigen Code indirekt und effektiv.

Hinweis aus dem obigen Code, dass die Rückruffunktion die Haupteingabe für den Code empfängt und die Hauptausgabe für den Code erstellt. Die C ++ - Future hat eine Funktion namens Sync (). Das erste Argument für diese Funktion ist die Rückruffunktionsreferenz. Das zweite Argument ist die Eingabe der Rückruffunktion. Die Sync () -Funktion kehrt zurück, ohne auf die Ausführung der Rückruffunktion zu warten, die die Rückruffunktion jedoch ausfüllen kann. Dies bietet asynchrones Verhalten. Während die Rückruffunktion weiter ausgeführt wird, wird die unten darunter. Dies ist wie ein ideales asynchrones Verhalten.

Das obige Programm wurde unten unter Berücksichtigung der zukünftigen Bibliothek und ihrer Sync () -Funktion umgeschrieben:

#enthalten
#enthalten
#enthalten
Verwenden von Namespace STD;
Zukunft Ausgang;
String CB (String STRI)

Rückkehr Stri;

void Principalfn (String -Eingabe)

output = async (cb, Eingabe);
Cout<<"principal function"<<'\n';

void fn ()

Cout<<"seen"<<'\n';

int main ()

String input = string ("Rückruffunktion");
PrincipalFn (Eingabe);
fn ();
String ret = Ausgabe.erhalten(); // wartet, bis der Rückruf bei Bedarf zurückkehrt
Cout<Rückkehr 0;

Die Sync () -Funktion speichert schließlich die Ausgabe der Rückruffunktion in das zukünftige Objekt. Die erwartete Ausgabe kann in der Funktion main () unter Verwendung der Get () -Mitlerfunktion des zukünftigen Objekts erhalten werden.

Abschluss

Eine Rückruffunktion ist eine Funktion, die ein Argument, kein Parameter, in einer anderen Funktion ist. Ein Rückruffunktionsschema benötigt eine Hauptfunktion und die Rückruffunktion selbst. Die Deklaration der Rückruffunktion ist Teil der Parameterliste der Hauptfunktion. Die Definition der Rückruffunktion ist im Funktionsaufruf der Hauptfunktion (in main ()) angegeben. Die Rückruffunktion wird tatsächlich innerhalb der Definition der Hauptfunktion aufgerufen.

Ein Rückruffunktionsschema ist nicht unbedingt asynchron. Um sicherzustellen, dass das Rückruffunktionsschema asynchron ist, machen Sie die Haupteingabe für den Code, die Eingabe der Rückruffunktion. Erstellen Sie die Hauptausgabe des Codes, die Ausgabe der Rückruffunktion; Speichern Sie die Ausgabe der Rückruffunktion in einer Variablen- oder Datenstruktur. Führen Sie in der Funktion main () nach dem Aufrufen der Hauptfunktion andere Anweisungen der Anwendung aus. Wenn die Ausgabe der Rückruffunktion benötigt wird, verwenden Sie sie und dann in der Funktion main () (lesen und anzeigen).