Methode übergeben
-
Hallo zusammen,
in meinem aktuellen Programm wird sehr viel berechnet, weshalb sehr viele Wertetabellen mit StringGrid erstellt werden. Ich habe immer eine Methode , die mir die Formel liefert, und eine, die die Tabelle erstellt.Hier ein Beispiel:
float __fastcall TKepler::VRotation (int i) { float R1 = i / Rmax; if (R1 <= 1) V = Vmax * R1; //Hier ist die Funktion else V = CGM / pow(i,0.5); return V; }//---------------------------------------------------------------------------- void __fastcall TKepler::Table1 (TStringGrid *grid) { grid->Cells[0][0] = "--------------------"; grid->Cells[1][0] = "V"; for (int i = 1; i<15; i++) { VRotation (i); grid->Cells[0][i] = "R = " + FloatToStr (i);//Hier wird die Tabelle erstellt grid->Cells[1][i] = FloatToStrF (V, ffNumber, 8, 2); } }
Nun ist es so, dass ich sehr viele Funktionen habe, weshalb auch sehr viele Tablemethoden. Sie heißen dann Table1, Table2, Table3 etc. Da dies sehr viel Quelltext einnimmt (und wahrscheinlich auch nicht so professionel ist), habe ich mir gedacht, dass eine ich Methode erstelle, die alle Tablemethoden ersetzen soll. Ich dachte an so etwas:
void __fastcall TKepler::Table (TStringGrid *grid, String title_left, String title_right, int loop_index_start, int loop_index_end, String function) { grid->Cells[0][0]= "----------------------"; grid->Cells[1][0]= title_right; for (int i=loop_index_start; i<loop_index_end; i++) { function; grid->Cells[0][i] = title_left + FloatToStr (i); grid->Cells[1][i] = FloatToStrF (V, ffNumber, 8, 2); } }
Alles wurde durch Variabeln ersetzt. Das klappt auch soweit, doch gibt es einen Hacken. Ich weiß nicht wie ich eine Mehtode (also hier die entsprechende mathematische Funktion) übergeben soll. Ich habe dies mit "function;" gekennzeichnet und als String vereinbart, was jedoch falsch sein müsste. Wie kann ich mittels eines Parameters eine Methode übergeben? Wenn dies funktionieren würde, dann würde auch meine allgemeine Tablefunktion funktionieren.
Vielen Dank für eure Hilfe
lg, freakC++
-
Hallo,
Du mußt hier doch keine Methode übergeben. Erzeuge dir ein Enum mit Einträgen für alle möglichen Funktionen und rufe die dann in deiner Tabellenfunktion über ein switch auf.
-
HEy,
sorry wenn ich fragen muss, aber was ist ein Enum? Meinst du, dass ich einfach in die Table-Mehtode alle MEthoden in ein switch-Gerüst reinschreibe? Wenn ja, dann wäre doch eher if-else besser, oder?Naja, vielleicht sollte mir erst klar werden, was du meinst
!!
Vielen Dank
lg, freakC++
-
freakC++ schrieb:
HEy,
sorry wenn ich fragen muss, aber was ist ein Enum?Nach deiner Beitragszahl solltest du das Schlüsselwort "enum" eigentlich kennen (Steht in nahezu jedem C++ Buch recht weit vorne). Nimm dir bitte ein x-Beliebiges Buch zu C++, schau im Index nach enum, oder benutze die google-Suche (C++ Grundlagenwissen).
cu André
P.S: Wobei ich persönlich die enum-Lösung unflexibel finde (zumindestens wenn sich wirklich nur die Funktionen unterscheiden, würde ich je nach Anwendungsfall ggf. zu den Bestandteilen aus den Namensräumen std::tr1/boost [je nach dem wie die Unterstützung von deinem Compiler für den TR1 ist, oder falls du eh boost verwendest] greifen [function, bind...]).
Wenn du aber bereits mit enum deine Probleme hast, würde ich eher nochmal die C++ Grundlagen verinnerlichen, dir dürfte oben genanntes ohne Grundlagen ziemlich unverständlich sein.
-
HEy,
sorry wenn ich fragen muss, aber was ist ein Enum? Meinst du, dass ich einfach in die Table-Mehtode alle MEthoden in ein switch-Gerüst reinschreibe? Wenn ja, dann wäre doch eher if-else besser, oder?Naja, vielleicht sollte mir erst klar werden, was du meinst
!!
Dennoch habe ich es noch mal auf einfacher Basis versucht. DAs sieht dann so aus:float __fastcall TKepler::VRotation (int i) { float R1 = i / Rmax; if (R1 <= 1) V = Vmax * R1; //mathematische Funktion else V = CGM / pow(i,0.5); return V; } //--------------------------------------------------------------------------- void __fastcall TKepler::Table (TStringGrid *grid, String title_left, String title_right, int loop_index_start, int loop_index_end, String function) { grid->Cells[0][0]= "----------------------"; grid->Cells[1][0]= title_right; for (int i=loop_index_start; i<loop_index_end; i++) { if (function=="VRotation") //allgemeine Tablefunktion. Ich würde dann auf un- { //eleganer Weise alle Funktionen mit if erwähnen VRotation(i); grid->Cells[0][i] = title_left + FloatToStr (i); grid->Cells[1][i] = FloatToStrF (V, ffNumber, 8, 2); } } } //--------------------------------------------------------------------------- void __fastcall TForm1::Button6Click(TObject *Sender) { Kepler1->Table(StringGrid,"R = ","Vrot",1,1, "VRotation"); //Anwendung der Tablefunktion! } //---------------------------------------------------------------------------
Dennoch funktioniert das leider nicht. Das StringGrid bleibt einfach leer. Außerdem bin ich mir nicht gan sicher bei dieser Zeile:
grid->Cells[0][i] = title_left + FloatToStr (i);
grid->Cells[1][i] = FloatToStrF (V, ffNumber, 8, 2);Hier wird jetzt die Variabel V verwendet. Diese wird in der Methode "VRotation" zurückgegeben. Normalerweise hat das funktioniert, aber ich habe sie global vereinbart und ich habe hier schon gelernt, dass das nicht gut ist.
Könnt ihr mir den Fehler oder die FEhler in diesem Quelltextauszug zeigen?
@asc: Ich habe das Buch "C++ für Kids" von Hans-Georg Schumann (bitte nich lachen
) durchgearbeitet. Darin ist dieser Ausdruck im Index nicht zu finden. Ich habe mir schon ein weiteres Buch angeschafft und werde dort mal gucken. Sonst stehe mir google zur Seite bzw. (hoffentlich) ihr!
Vielen Dank
lg,freakC++PS. Da sind wohl meine Einträge verrutscht. Sorry. Ach ja...ich zähle mich durchaus noch zu einem Anfänger, der nur viel fragt und viel lernen will!!!
-
Hallo,
richtig, die Funktion gibt "V" zurück! Aber an was?
double V = VRotation(i); // macht vllt mehr Sinn ist aber nicht die Lösung des Problems
Du übergibst 1 als loop_index_start und 1 als loop_index_end?!
for (int i=1; i<1; i++) {} // Diese Schleife wird nie ausgeführt...
LG, Micha
-
Hallo
freakC++ schrieb:
sorry wenn ich fragen muss, aber was ist ein Enum? Meinst du, dass ich einfach in die Table-Mehtode alle MEthoden in ein switch-Gerüst reinschreibe? Wenn ja, dann wäre doch eher if-else besser, oder?
Enums sind grundlegende Datentypen. Diese eigenen sich besonders gut für switch-Konstruktue :
enum Status {A, B, C}; ... Status mein_status = A; switch (mein_status) { case A : ShowMessage("A"); break; case B : ShowMessage("B"); break; case C : ShowMessage("C"); break; default : ShowMessage("unbekannt"); };
bis bald
akari
-
zu enum
http://tutorial.schornboeck.net/enum.htm
@asc
Ich hatte extra erstmal enums und nicht Funktionszeiger oder gar boost::function erwähnt, um es nicht zu kompliziert zu machen.
-
Hallo zusammen,
vielen Dank für die Tipps. Ich habe mir mir das Tutorial angeschaut und mich nochmals über enums schlau gemacht. Dennoch bin ich mir über den Syntax und auch noch nicht völlig über den Gebrauch klar. Ich wollte folgendes versuchen, doch klappte das nicht, da - wie schon gesagt - der Syntax noch nicht so klar ist.void __fastcall TKepler::Table (TStringGrid *grid, String title_left, String title_right, int loop_index_start, int loop_index_end, int modus) { grid->Cells[0][0]= "----------------------"; grid->Cells[1][0]= title_right; enum {A,B,C}; //ich wollte jetzt hier ein enum erstellen, das A, B, C enthält switch (modus) //jetzt kann ich fast nur raten: Ist es richtig anzunehmen, { // dass ich als Parameter nun A, B oder C schreibe und so durch case 1: // die switch-Struktur geleitet werde??? ShowMessage("Hallo"); break; case 2: ShowMessage("Gude"); break; case 3: ShowMessage ("Hey"); } for (int i=loop_index_start; i<loop_index_end; i++) { VRotation(i); grid->Cells[0][i] = title_left + FloatToStr (i); grid->Cells[1][i] = FloatToStrF (V, ffNumber, 8, 2); } } //---------------------------------------------------------------- Kepler1->Table(StringGrid,"R = ","Vrot",1,15, "A"); //muss jetzt hier z.B. A //stehen??
So, ich kann mir vorstellen, dass das gerade totaler Schwachsinn war, wie ich es angenommen habe, doch würde ich mich freuen, wenn ich durch eure Hilfe "enum" in meinen C++ Wortschatz aufnehmen kann, denn ich möchte schließlich auch mehr lernen
Ich habe mich nochmals hier (http://www.cpp-tutor.de/cpp/le08/le08_02.htm#themen) schlaugemacht, da ich die Beispiel sehr anschaulich fand. Dennoch habe ich sie nicht ganz verstanden. Außerdem habe ich gesehen, dass mein oben gepostetes Beispiel definitiv falsch sein muss. Leider konnte ich dies jedoch noch nicht berichtigen, da ich die "enum-Angelegenheit" noch nicht ganz verstehe.
Könnt ihr mir weiterhelfen??
Vielen Dank
lg, freakC++PS: @RandomAccess85: Das mit dem for-Schleifenindex war natürlich wieder ein blöder Fehler von mir! Danke!!!
-
Irgendwie seh ich nicht, was Du genau willst.
Du hast eine Funktion (Methode) Table(n) {für mehrere Grids}
in dieser soll immer eine bestimmte Berechnung erfolgen UND das jeweilige Grid gefüllt ewerden.
Ist das IMMER nur die eine Methode ? (VRortaion)
Oder: für jedes Grid ne andere?
Oder abhängig von noch was anderem ??? jeweils eine wählbare (für jedes Grid jede Funktion wählbar?)*****************************************************************************
Die Funktion muss nicht übergeben werden, die ist ja eine Methode von TKepler, also in jeder Methode von TKepler einfach anwendbar.Natürlich KANN auch eine übergeben werden, aber dann NICHT als Zeichenkette.
VRotation sollte:
floatz V;
als lokale Variable enthalten!!!
als letztes
return V;
ausführen!!!Du kannst jedem Grid die Property Tag durchnummerieren
Dann kann in Methode Table das jeweilige Grid ausgewertet werden:
switch(Grid->Tag) { case 0: //hier rufst Du die nötiger Funktionauf //z.B: //V=VRotation(1); break; case 1: //hier rufst Du die nötiger Funktionauf break; case 2: case 3: //hier rufst Du die nötiger Funktionauf break; case 4: case 7: //hier rufst Du die nötiger Funktionauf break; default: //falls kein Tag getroffen wurde break; }
Für Grid->Tag 2 und 3 bzw. 4 und 7 wird jeweils eine gemeinsame bearbeitung aufgerufen
Gruss
Frank