Memberfunktion übergeben
-
Hallo zusammen,
ich bin noch relativ unerfahren mit c++ genauso wie in diesem Forum und versuche ein Doppelpendel zu programmieren.
Dazu habe ich erstmal zwei Klassen erstellt:
- Klasse Doppelpendel
- Klasse ODE
In der erstgenannten Klasse werden Eigenschaften des Pendels definiert, wie die Masse, die Länge der einzelnen Stangen und die Freiheitsgrade (Winkel Θ1, Θ2 und die Ableitungen davon).
Desweiteren enthält es eine Funktion diff, welche jeweils für den aktuellen Zeitschritt die ersten und zweiten Ableitungen der freien Variablen errechnet. Diese Funktion wird bei der Integration benötigt.
Zusätzlich habe ich noch eine Memberfunktion "update" reingenommen, welche die Winkel und Winkelgeschwindigkeiten für den nächsten Zeitschritt aktualisieren soll.So, und da liegt mein kleines Problem:
Damit die Methode update die Winkel aktualisieren kann, muss die DGL gelöst werden, was in der Klasse ODE getan wird.Die Klasse ODE enthält außer der Konstruktoren und Destruktoren zur Zeit noch eine Memberfunktion RK, welche mit dem Runge-Kutta Verfahren die DGL integriert.
Um dies machen zu können benötigt RK die Funktion diff der Klasse Doppelpendel.Ich wollte es so lösen, dass innerhalb der update-Funktion ein ODE-Objekt erstellt wird, welches die Funktion diff übergeben bekommt und die neue Position ausgibt.
Etwas Code dazu:
class DoppelPendel{ public void DoppelPendel::diff(const float t, const float th[dim], float diff[dim]) { ... ... // diff ist die errechnete Ableitung } void DoppelPendel::update(const float dt, const float t){ float thetaout[dim]; ODE DPRK(eps,dim); DPRK.RK(this->diff, dt, t, this->theta, thetaout); this->newPosition(thetaout); //Aktualisierung der Position } } class ODE{ void RK(void rhs(const float tt, const float y[], float dy[]), const float& h, const float& t, const float yin[], float yout[]); // zur Ausgabe wird yout verwendet }Ok, ich hoffe das es einigermaßen verständlich geworden ist, was ich anstellen möchte. Falls es auf diese Weise nicht funktioniert, dann wäre ich für eine andere Herangehensweise offen. Es ist mir nur wichtig, dass der DGL-Löser in eine Klasse ist.
MfG
muvik
-
Was du suchst sind Klassenmethodenzeiger, z.B.
void (Doppelpendel::*func)(/*Parameter*/);Nachteil ist, daß der Name der Klasse fest vorgegeben ist.
Ich hoffe, du hast deine beiden Klassen in Quellcode (.cpp) und Headerdateien (.h bzw. .hpp) aufgeteilt? Sonst wirst du Probleme beim gegenseitigen Einbinden kriegen.
Einfacher und flexibler wärst du aber mit boost::function<...> (www.boost.org).
-
Danke für die Antwort erstmal.
Da der Klassenname nun jedoch vorgegeben wäre, ist das keine gute Lösung, oder?
Ich habe die Klassen in header-Dateien und Quellcode eingeteilt.
In der Klasse ODE möchte ich diverse Löser für DGL implementieren.
Da wäre die Frage, ob das überhaupt sinnvoll ist, die DGL-Löser in einer Klasse zusammenzufassen, um sie bei div. Aufgaben zu verwenden.
Da ich keine Erfahrung mit objektorientierter Programmierung habe, weiß ich nicht wie ich dass sonst geschickt lösen könnte.Wie würdest Du/Ihr da vorgehen?
Wichtig ist mir dabei, dass ich aus einer Klasse heraus (z.B. Doppelpendel) den Löser aufrufen kann und ihm eine Funktion der Klasse übergeben kann.
Es ist wohl wenig sinnvoll die Funktion bei jeder Programmieraufgabe in die neue Klasse zu kopieren, wie ich das workaround-mäßig bei dem Doppelpendel getan habe.
Ich würde mich über kreative Antworten freuen.
MfG
muvik
-
muvik schrieb:
In der Klasse ODE möchte ich diverse Löser für DGL implementieren.
Da wäre die Frage, ob das überhaupt sinnvoll ist, die DGL-Löser in einer Klasse zusammenzufassen, um sie bei div. Aufgaben zu verwenden.
Da ich keine Erfahrung mit objektorientierter Programmierung habe, weiß ich nicht wie ich dass sonst geschickt lösen könnte.Ich denke nicht, dass das schlecht ist. Wenn die Klasse
ODEaber keinen Status hat und nur Methoden anbietet, könntest du auch einen NamensraumODEschreiben und die Funktionen dort platzieren.muvik schrieb:
Wie würdest Du/Ihr da vorgehen?
Wichtig ist mir dabei, dass ich aus einer Klasse heraus (z.B. Doppelpendel) den Löser aufrufen kann und ihm eine Funktion der Klasse übergeben kann.
Gibt es denn mehrere Funktionen mit gleicher Signatur wie
diff(), die du der KlasseODEzur Berechnung übergeben kannst? Falls ja, kann es durchaus sinnvoll sein, Memberfunktionszeiger zu verwenden. Eine kleine Übersicht erhältst du hier.Falls nein (d.h. es wird immer nur
diff()benötigt), warum befindet sich die Funktion nicht inODEselber?
-
Nexus schrieb:
Ich denke nicht, dass das schlecht ist. Wenn die Klasse
ODEaber keinen Status hat und nur Methoden anbietet, könntest du auch einen NamensraumODEschreiben und die Funktionen dort platzieren.OK, danke für den Tipp, das werde ich mir mal anschauen. Bisher stehen die Löser in einer Klasse, da ich es möglichst allgemein halten wollte. Als zusätzliche Variablen habe ich eine Konvergenztoleranz und die Dimension des Problems definiert, was jedoch auch dem jeweiligem Löser immer übergeben werden kann.
Nexus schrieb:
Gibt es denn mehrere Funktionen mit gleicher Signatur wie
diff(), die du der KlasseODEzur Berechnung übergeben kannst? Falls ja, kann es durchaus sinnvoll sein, Memberfunktionszeiger zu verwenden.Die Funktion
diff(...)ist problemspezifisch und liefert die Ableitung der Variable, die integriert werden soll. Im Moment habe ich nur diediff()-Funktion des Doppelpendels, aber das soll ja nur der Anfang sein. Also: ja, es gibt bzw. wird noch mehrere Funktionen mit gleicher Signatur geben.Ich schaue mir mal den Link durch und tauche dann bestimmt mit weiteren Fragen hier auf. Also danke soweit.
MfG
muvik