Funktion in struct??
-
void test1() { cout << "eins" << endl; } void test2() { cout << "zwei" << endl; } void test3() { cout << "drei" << endl; } void test4() { cout << "vier" << endl; } int main() { typedef void ( *function_t ) (); function_t functions[4]; functions[0] = test1; functions[1] = test2; functions[2] = test3; functions[3] = test4; for( int i = 0; i < 4; i++ ) functions[i](); cin.get(); }
-
Hallo,
ahh super! Dann hab' ich es begriffen, wie es läuft. Da ich aber was lernen will, würde ich mich sehr freuen, wenn Ihr mir noch die folgenden Fragen beantworten könnt.1.) Wenn ich eine "normale" Funktion definiere wie diese:
int foo(int i){return i*i;}
dann wird dafür ein bestimmter Speicherplatz reserviertö. Was passiert nun bei dieser Funktion:
double (*myFunc2[4])(double k) = {NULL};
Wird da auch eine feste Speichergröße reserviert?
2.) Spricht man hier überhaupt von einer Funktion. Solch ein "Konstrukt" war mir bis jetzt unbekannt. Zum einen habe ich ein Array und zum anderen eine Funktion mit Array. Könntet ihr mir das noch ein bisschen erklären, da ich nicht einfach Code von einer Website übernehmen will ohne sie zu vertehen.
3.) Könnte man solch ein Funktions - Array auch dynamisch deklarieren?
Vielen Dank
-
1. Ja, da wird genau so viel Speicher reserviert, wie es nötig ist für 4 Funktionszeiger. (Das sind ja auch "nur" Zeiger).
Mit einem Typedef siehst du dann, dass es genau das gleiche ist, wie wenn du ein normales Array von z.B int's anlegst.2. Das ist ein Funktionszeiger (function pointer). Das besagt ja nur, dass diese Variable auf eine Funktion zeigt. Und du kannst die Funktion auch aufrufen ohne ihren genauen Namen zu kennen.
3. Jap, klar.
-
Hallo,
noch eine Frage. wenn ich jetzt alles in eine struct packe, warum funktioniert das dann nicht:struct Sinus { double fx (double k) {return sin(k);} double fx1 (double k) {return cos(k);} double fx2 (double k) {return -sin(k);} double fx3 (double k) {return -cos(k);} } Sin; ... double (*mySin[4])(double k) = {&Sin.fx, &Sin.fx1, &Sin.fx2, &Sin.fx3}; //Die Schreibweise funktionieren nur, wenn die 4 Funktionen klassenlos sin.
vielen Dank
-
Wollte nur noch erwähnen, dass, falls es bei Funktoren bleibt, immer ein "const" eingefügt werden sollte, falls möglich:
struct TrgSin { double fx(double k) const {return sin(k);}; // ^^^^^ };
struct schrieb:
Hallo,
noch eine Frage. wenn ich jetzt alles in eine struct packe, warum funktioniert das dann nicht?Weil es sich um nicht-statische Elementfunktionen handelt. Zeiger auf solche Funktionen sind nicht mit "normalen" Funktionszeigern kompatibel, weil diese Funktionen noch den zusätzlichen this-Parameter eines bestimmten Typs bekommen (in Deinem Fall ein Zeiger auf TrgSin).
Die Elementfunktionen im struct bringen Dir eh nichts, wenn Du mit Funktionszeigern arbeiten willst.
Gruß,
SP
-
Warum genau? Ich hatte nicht vor, die Ausgabedateien ändern zu lassen? Kannst Du das noch erklären?
Was mache ich denn bei der struct falsch?
Danke
-
also die structs sind doch sicher so wie in c und da kannst du keine functionen in ein struct packen sondern nur zeiger auf functionen...
das ganze muß dann so ausschauen...
struct Sinus { double (*fx)(double); double (*fx1)(double); double (*fx2)(double); double (*fx3)(double); }mySin;
was willst denn damit?
double (*mySin[4])(double) = {Sin.fx, Sin.fx1, Sin.fx2, Sin.fx3}; //Die Schreibweise funktionieren nur, wenn die 4 Funktionen klassenlos sin.
hatte den fehler auch letztens in nem proggie, functionen sind bereits zeiger also kannst dir das & schenken, anscheinend macht es aber nichts es mit dazu zu schreiben?
lg lolo
-
noobLolo schrieb:
also die structs sind doch sicher so wie in c und da kannst du keine functionen in ein struct packen sondern nur zeiger auf functionen...
Falsch.
noobLolo schrieb:
[...]
hatte den fehler auch letztens in nem proggie, functionen sind bereits zeigerFalsch.
noobLolo schrieb:
also kannst dir das & schenken,
Das kann man sich schenken, weil es eine implizite Konvertierung von Funktionen zu Funktionszeigern gibt ("function to pointer decay").
Gruß,
SP
-
und was muss ich dann ändern, damit ich meine Funktionen in der struct lassen kann?
-
struct schrieb:
und was muss ich dann ändern, damit ich meine Funktionen in der struct lassen kann?
Wieso willst du die denn unbedingt in ein
struct
nehmen? Mach aus deinemstruct
doch eher einennamespace
und belass die freien Funktionen.Sonst brauchst du dann nämlich immer ein Objekt von diesem
struct
um die gespeicherten Funktionen aufzurufen. Wahnsinnig umständlich und unnötig, da du ja in deinemstruct
nichts speicherst.Aber einfach damit du es noch siehst, wie man Memberfunktionen speichert und aufruft:
#include <iostream> struct Test { void foo(int x) { std::cout << "Test::foo(" << x << ");\n"; } }; int main() { typedef void (Test::*TestMemFunc)(int); // <- Funktionstyp TestMemFunc func = &Test::foo; // <- Zuweisung Test test; (test.*func)(5); // <- Aufruf return 0; }
Grüssli
-
Mach die Funktionen statisch:
struct MyMath { static double fx (double k) { return sin(k); } static double fx1 (double k) { return cos(k); } static double fx2 (double k) { return -sin(k); } static double fx3 (double k) { return -cos(k); } };
Besser wäre aber dafür ein eigener Namensbereich, d.h.:
namespace MyMath { double fx (double k) { return sin(k); } double fx1 (double k) { return cos(k); } double fx2 (double k) { return -sin(k); } double fx3 (double k) { return -cos(k); } }
Zugriff dann über den Namen des Namensbereichs (bzw. der Struktur):
double (*myMath[4])(double k) = {&MyMath.fx, &MyMath.fx1, &MyMath.fx2, &MyMath.fx3};
Ohne das 'static' hast du normale Klassenmethoden erzeugt und dafür bräuchtest du dann entsprechend Klassenmethodenzeiger:
double (MyMath::*myMathMethods[4])(double);
Und der Aufruf dann über ein konkretes Objekt:
MyMath myMath; double y = (myMath.*myMathMethods[0])(3.1415926535897932); // oder per Zeiger dann mit ->*
-
Hallo Th69,
vielen Dank dafür. Eigentlich ist das mit dem namespace schöner, doch wenn ich das genau so mache wie Du, dann erhalte ich folgende Fehler:Unzulässige Verwendung des Namensbereichs 'Sin'
Referenz-Variable 'Sin' muß initialisiert sein
Mache ich da was falsch oder liegt der Fehler ganz anderswo?
Vielen Dank auch dir, Dravere. Deine Erklärung hat mir sehr geholfen.
-
Ups, sorry.
Bei Namensbereichen bzw. Klassen/Strukturen muß man ja den '::' als Trenner verwenden (ich programmiere in letzter Zeit mehr C#-):double (*myMath[4])(double k) = {&MyMath::fx, &MyMath::fx1, &MyMath::fx2, &MyMath::fx3};
P.S: Der Name 'Sin' macht ja keinen Sinn, weil du dort ja verschiedenen trigonometrische Funktionen verwendest (nicht nur den Sinus-)
-
Hallo,
aahh klar!!! Hätte ich auch selber sehen müssen. Doch der Name Sin macht hier Sinn, da das die ABleitungen des Sinus sind. Die brauche ich hier.Vielen Dank für eure Hilfe