Funktion als Rückgabetyp
-
Hey,
dass man Funktionen in C++ per Parameter übergeben kann, durfte ich vor einiger Zeit schon erstaunt feststellen. Aber kann man Funktionen auch zurückgeben?
Ich habe es so versucht, aber mein Compiler mag das nicht...
(double (*fkt)(double, double)) get_fkt(int);LG Noob
-
richtig so.
was du da verwendest ist nicht nur die benötigte definition deines rückgabewertes sondern auch ein name dabei
mach mal das hier draus:
(double (*)(double, double)) get_fkt(int);oder noch besser
typedef (double (fkt*)(double, double)); fkt getFkt(int);
-
Geht leider auch nicht.

Die selbe Fehlermeldung:
error C2062: 'double'-Typ unerwartet
-
Skym0sh0 schrieb:
oder noch besser
typedef (double (fkt*)(double, double)); fkt getFkt(int);Eher
typedef double (*fkt)(double, double); fkt getFkt(int);Wie es ohne Typedef geht... weiss ich nicht

-
Der Stern ist auch auf der falschen Seite. Und auch die Klammern werden von VS nicht geschluckt.
So funktioniert's:
typedef double (*fkt)(double, double);
-
Skym0sh0 schrieb:
richtig so.
was du da verwendest ist nicht nur die benötigte definition deines rückgabewertes sondern auch ein name dabei
mach mal das hier draus:
(double (*)(double, double)) get_fkt(int);Sollte auch nicht gehen. Richtig ist:
double (*get_fkt(int))(double, double)Nimm lieber einen Typedef

-
Ja super, es funktioniert!

Eines der Mysterien, auf denen die meisten Tutorials keine Antwort haben.

Danke!

-
Eine Funktion als Rückgabewert ist schon ziemlich abgefahren...

Fällt jmd. zufällig auch ein Beispiel ein an wo so etas Sinn macht?
-
redrew99 schrieb:
Fällt jmd. zufällig auch ein Beispiel ein an wo so etas Sinn macht?
Naja, für GetProcAddress() und ähnliche Funktionen wäre es praktisch.
Wobei GetProcAddress() lieber nen void* zurückgibt, bei dem das Casten in einen Funktionszeiger laut Standard nicht definiert ist (UB oder implementation defined - weiss ich jetzt nicht).
-
ok, passt nicht ganz, aber hat jemand irgendwo nen gutes tut für solche funktionsspielchen?
habe auch schon davon gehört, und das wäre natürlich mega, wenn ich es selbst anwenden könnte
also ein tutorial hauptsächlich darüber, wie ich ne funktion übergebe.
-
redrew99 schrieb:
Eine Funktion als Rückgabewert ist schon ziemlich abgefahren...

Fällt jmd. zufällig auch ein Beispiel ein an wo so etas Sinn macht?Die C-Standardfunktion signal.
anti-freak schrieb:
gutes tut
Widerspruch in sich.
-
Auto, tut-tut!
-
ichbineinnoob schrieb:
Hey,
dass man Funktionen in C++ per Parameter übergeben kann, durfte ich vor einiger Zeit schon erstaunt feststellen. Aber kann man Funktionen auch zurückgeben?
Ich habe es so versucht, aber mein Compiler mag das nicht...
(double (*fkt)(double, double)) get_fkt(int);LG Noob
Eigentlich nicht Funktionen, sondern Zeiger oder Referenzen darauf. Interessanterweise macht der Compiler von sich aus Zeiger daraus, wenn man Funktion schreibt. Aber nur bei Parametern. Beim Rückgabetyp ist es schlicht nicht erlaubt.
typedef double fkt(double,double); void do(fkt f); // äquivalent zu void do(fkt* f); // oder ausgeschrieben void do(double f(double,double)); // bzw. void do(double (*f)(double,double)); // wer will auch void do(fkt& f); // das kann aber nur mit Funktionen gefüttert werden, void do(double (&f)(double,double)); // Zeiger muss man erst explizit dereferenzieren, also nicht wirklich sinnvoll // aber fkt get_fkt(int); // Fehler! fkt* get_fkt(int); // oder auch fkt& get_fkt(int); // allerdings ohne semantische Vorteile //ausgeschrieben double (*get_fkt(int))(double,double); // oder double (&get_fkt(int))(double,double);Danke, K&R. Trotz dieser *hust* Eleganz ist es nicht möglich, Eine Funktion zu deklarieren, die einen Zeiger auf sich selbst zurückgibt (mit dem richtigen Typ).
ach ja, dann geht auch noch C++11:auto get_fkt(int) -> fkt*; auto get_fkt(int) -> double (*)(double,double); // usw.etwas besser lesbar, erlaubt aber auch nicht mehr als die alte Syntax.
auto get_fkt(int a) -> decltype(&get_fkt);wäre schön, geht aber nicht, weil Namen erst am Ende aller Deklaratoren bekannt sind, im decltype ist der Funktionsname noch unbekannt.
-
anti-freak schrieb:
ok, passt nicht ganz, aber hat jemand irgendwo nen gutes tut für solche funktionsspielchen?
habe auch schon davon gehört, und das wäre natürlich mega, wenn ich es selbst anwenden könnte
also ein tutorial hauptsächlich darüber, wie ich ne funktion übergebe.Das ist ein Einzeiler:
Funktionen können weder als Parameter an eine Funktion übergeben werden, noch zurückgeliefert werden, da es den Datentyp function oder wie auch immer das genannt werden soll, nicht gibt. Lambdafunktionen des neuesten C++ Standards mögen etwas ähnliches sein, dazu kann ich aber nix sagen, da ich zu wenig darüber weiß.Na gut, waren jetzt doch mehr als eine Zeile.
Als Ersatz können Zeiger auf Funktionen definiert werden. Das geht sehr einfach:
1. Schritt: erstelle einen Prototypen:
<type> <functionName>( <type> <param>, ... );
Beispiel:int compare( const char *s1, const char *s2);2. Schritt: füge Klammern um den Funktionsnamen ein:
<type> (<functionName>) ( <type> <param>, ... );
Beispiel:int (compare)( const char *s1, const char *s2);3. Schritt: setze den Zeigeroperator vor dem Funktionsnamen:
<type> (*<functionName>) ( <type> <param>, ... );
Beispiel:int (*compare)( const char *s1, const char *s2);4. Schritt: gibt dem Zeiger 'nen anständigen Namen:
<type> (*<pointerName>) ( <type> <param>, ... );
Beispiel:int (*comparePtr)( const char *s1, const char *s2);Zum Befüllen des Zeigers schreibst Du einfach die Adresse einer Funktion mit dem passenden Prototypen rein. Die Adresse erhälst Du, in dem Du den Funktionsnamen ohne Parameterliste schreibst.
Beispiel:
comparePtr = compare;Zum Derefenezieren des Funktionszeigers schreibst Du den Namen des Zeigers mit Parameterliste:
Beispiel:
int result = comparePtr( "Hello", "World" );Wenn Du mehr als einen Zeiger auf so eine Funktion brauchst, ist es sinnvoll sich mit typedef einen Typ zu definieren:
typedef int (*comparePtrType)( const char *s1, const char *s2); ... comparePtrType comparePtr = compare;Das sollte es sein.
mfg Martin
-
mgaeckler schrieb:
Funktionen können weder als Parameter an eine Funktion übergeben werden, noch zurückgeliefert werden, da es den Datentyp function oder wie auch immer das genannt werden soll, nicht gibt.
Da du den neuen Standard erwähnt hast, was ist mit std::function?
-
mgaeckler schrieb:
Funktionen können weder als Parameter an eine Funktion übergeben werden, noch zurückgeliefert werden, da es den Datentyp function oder wie auch immer das genannt werden soll, nicht gibt.
Das ist auf subtile Weise richtig. Es gibt Funktionstypen, aber Funktionstypen sind keine Objekttypen (oder Datentypen wenn du sie so nennen willst).
-
Fällt jmd. zufällig auch ein Beispiel ein an wo so etas Sinn macht?
Unter reinem c++ wohl eher seltener, weil es fuer c++ bessere Mittel gibt (Interfaces / virtualitaet).
bleibt C und C kompatiblitaet mit c++ ....bei C wird man aber wohl eher keinen funktionspointer als rueckgabewert waehlen, sondern eher den Fehlercode, der eigentliche rueckgabewert ist dann in den paramatern als zeiger auf ... modeliert.
Ciao ...
-
set_new_handler Ist z.B. eine Funktion aus dem C++-Standard, die einen Funktionspointer zurückgibt. Gibt afaik noch ein paar andere...
-
set_unexpected und set_terminate fallen mir da ein.
-
redrew99 schrieb:
Eine Funktion als Rückgabewert ist schon ziemlich abgefahren...

Fällt jmd. zufällig auch ein Beispiel ein an wo so etas Sinn macht?Mal so ein Vorschlag:
qsort erwartet als einen der Parameter die Adresse einer Vergleichsfunktion. Dummerweise wird weder der Vergleichsfunktion noch qsort das Sortierkriterium mitgegeben. Daher wäre folgenden Szenario denkbar:
typedef int (*comparePtrType)( const void *e1, const void *e2 ); int compareNames( const void *e1, const void *e2 ); int compareSizes( const void *e1, const void *e2 ); int compareAges( const void *e1, const void *e2 ); comparePtrType getCompareFunc( int criteria ) { switch( criteria ) { case 0: return compareNames; case 1: return compareSizes; case 2: return compareAges; } return NULL; } void sortData( void *data, size_t numElements, size_t dataSize, int criteria ) { comparePtrType compareFunc = getCompareFunc( criteria ); if( compareFunc ) qsort( data, numElements, dataSize, comparefunc ); }Hab's jetzt nicht übersetzt sondern nur so hingeschrieben. Tippfehler müsst Ihr daher selbst beheben.
mfg Martin