Leichte Verrbung in C++
-
Salü!
Ich habe mal in Java einen Parser geschrieben, der mathematische Funktionen einlesen und auswerten kann. Nun hatte ich mir mal überlegt den eventuell in C++ umzuschreiben. (Ich habe zuerst Java gelernt und bin jetzt an C++).
Ich habe nun folgenden Java-Code (ist natürlich gekürzt):
Das Interface Function:
public interface Function { public boolean validNrOfArguments( int count ); public double calculate( double[] values ); }Und dazu eine Klasse Parser:
package parser; import java.util.HashMap; import java.util.Map; public class Parser { private Map<String, Function> functions = new HashMap<String, Function>(); public Parser() { functions.put("+", new Function(){ public boolean validNrOfArguments( int count ){ return count == 1; } public double calculate( double[] values ){ return values[0]; } }); } }Meine Frage wäre nun, wie man das am besten in C++ implementieren würde. Natürlich, man könnte eine Klasse schreiben, allerdings scheint mir das etwas übertrieben für so etwas kleines.
Gibt es da etwas "leichteres" als Klassen wie interfaces in C++? Oder muss man da wirklich eine neue Klasse erstellen? Oder schreibt man dazu einfach ein file, in dem gar keine Klase ist?Da ich gerne guten Code schreiben möchte und nicht einfach irgend einen Code wäre ich froh, wenn mir jemand etwas dazu sagen könnte.
-
Ich würde eine Basisklasse Function erstellen, die nen operator() implementiert.
Diese kannst du wunderbar in ne map legen.
Code ungetestet:class Function { virtual double operator () ( double left, double right) const =0; }; class AddFunction : public Function { double operator() ( double left, double right ) const {return left + right; } }; class Parser { std::map<string, Function*> functions; public: Parser() { functions["+"] = new AddFunction; } };Wobei du natürlich anstelle von Funktoren auch Funktionspointer verwenden kannst.
Du kannst dir überlegen dass das nicht immer gut geht.
Es gibt binäre Operatoren (wie +) und unäre Operatoren (Wurzel).
Deshalb wären vllt. zwei Basisklassen nicht schlecht.
-
Gibt verdammt viele Möglichkeiten, wie man dies umsetzen könnte. Ich kann da eigentlich fast nur einen Tipp geben:
Probiere nicht ein Java Problem mit C++ Mittel zu lösen.Oder andersrum:
Programmiere in C++ nicht wie in Java.Oder nochmals anders, allerdings auf dein Problem bezogen:
Überlege dir die Architektur neu und vergiss dabei Java. In C++ löst man Dinge im allgemein ganz anders, also von Grund auf anders. Wenn du nun immer wieder Teile für Teile aus Java nach C++ portierst, dann hast du am Ende ein Java Programm in C++ geschrieben, was nur grauenhafte Resultate haben kann. Portier nicht den Code sondern die Idee.Grüssli
-
Hi!
Danke ersma für eure Antworten!
@ l'abra d'or
Jap, so etwas ähnliches hatte ich mir auch schon überlegt. Ich hatte es ein bisschen übertrieben gefunden dafür eine Klasse zu erstellen, aber in C++ geht es wohl nicht ohne. Ich werds mal so versuchen.@ Dravere
Ich glaube ich werde mir mal ein weiteres C++ Buch kaufen, wo einem gezeigt wird was man in C++ machen und was nicht machen soll. Irgendwo in einem anderen Thread ist mir mal ein Buch vorgeschlagen worden.
Ist für mich ziemlich schwer umzudenken von Java zu C++.
-
icarus2 schrieb:
@ Dravere
Ich glaube ich werde mir mal ein weiteres C++ Buch kaufen, wo einem gezeigt wird was man in C++ machen und was nicht machen soll. Irgendwo in einem anderen Thread ist mir mal ein Buch vorgeschlagen worden.
Ist für mich ziemlich schwer umzudenken von Java zu C++.Hier werden so ziemlich alle gängigen Werke, die man als C++ Programmierer haben sollte:
http://www.c-plusplus.net/forum/viewtopic-var-t-is-251551.html
-
Danke

-
icarus2 schrieb:
Ich habe mal in Java einen [...] Nun hatte ich mir mal überlegt den eventuell in C++ umzuschreiben. Ich habe zuerst Java gelernt und bin jetzt an C++.
Ich war in der gleichen Situation, erst Java, dann C++.
icarus2 schrieb:
Meine Frage wäre nun, wie man das am besten in C++ implementieren würde.
Gute Frage; denn es ist wirklich so, dass man nicht versuchen sollte, das Design 1:1 zu übertragen.
Laufzeitpolymorphie/Interfaces ist in Java eines der wenigen Abstraktionsmittel zur Entkoppelung einzelner Komponenten. Wenn Du anfängst genauso in C++ zu programmieren, wird Dir wahrscheinlich irgendwann der Garbage-Collector fehlen. Das ist wie bei dieser Metapher mit dem Hammer. Wenn Du als einziges Werkzeug nur einen Hammer kennst, sieht alles aus wie ein Nagel. C++ bietet zusätzlich andere Sprachmittel an, die einem das Leben leichter machen und Dich darüber hinwegtrösten können, dass es keinen GC gibt. Nach einer Weile hat man sich dran gewöhnt und den Dreh raus und muss auch nicht besonders viel dabei nachdenken. Man muss nur die Sprachmittel zu schätzen wissen und ein Gefühl für deren effektiven Einsatz bekommen. Ich vermisse den GC heute nicht mehr.
Aber die C++ Standardbibliothek könnte ruhig noch den einen oder anderen Baustein mehr bieten. Ich gehe zB davon aus, dass std::unique_ptr (im nächsten C++ Standard) sehr praktisch in bestimmten Fällen werden wird.
Man sollte auch mal nachlesen, wie das mit dem Konzept der getrennten Übersetzung funktioniert und was es mit den Header-Dateien aufsich hat. Die "Eine-Definition-Regel" sollte in jedem guten C++ erklärt werden. Kann ich nur empfehlen, sich ein passendes Buch zu besorgen.
Dass man nicht alles in Klassen packen muss, weißt Du hoffentlich schon. In C++ geht der Trend dahin, freie Funktionen statt public-Methoden zu schreiben, sofern sie nicht direkt auf private Elemente zugreifen müssen. Jede freie Funktion f, die in demselben Namensraum N wie die Klasse K definiert ist und als Parameter irgend etwas entgegen nimmt, wo K als Typ auftaucht (zB einen Zeiger auf K), dann gehört die Funktion logisch zum "Interface" und kann -- dank ADL -- aufgerufen werden, ohne den Namen der Funktion qualifizieren zu müssen.
icarus2 schrieb:
Natürlich, man könnte eine Klasse schreiben, allerdings scheint mir das etwas übertrieben für so etwas kleines.
Gibt es da etwas "leichteres" als Klassen wie interfaces in C++? Oder muss man da wirklich eine neue Klasse erstellen?in welcher Hinsicht ist das übertrieben? Was genau meinst Du mit leichter?
icarus2 schrieb:
Da ich gerne guten Code schreiben möchte und nicht einfach irgend einen Code wäre ich froh, wenn mir jemand etwas dazu sagen könnte.
Learning by doing + gute Bücher lesen.
Dravere schrieb:
Programmiere in C++ nicht wie in Java.

icarus2 schrieb:
Hi!
Ist für mich ziemlich schwer umzudenken von Java zu C++.Ja, das unterschätzt man leicht. Aber so nach'nem halben Jahr spätestens, hat man das gröbste überstanden. Danach gibt es nur mal wieder Sprachfeinheiten, die man vielleicht mal nachgucken muss. Wenn man Templates richtig verstehen und anwenden können will, wäre ein Buch dazu auch nicht verkehrt.
Gruß,
SP
-
Danke für den Buch-Tipp. Ich glaube ich werde mir das Buch Effective C++ einmal bestellen. Das ist mir schon von vielen Leuten empfohlen worden.
Ich habe als Einsteigerlektüre den Primer gelsen (sehr gutes Buch meiner Meinung nach). Ich habe mich mittlerweile auch ziemlich stark an die Syntax von C++ und einige Spracheigenschaften gewohnt. Aber das Umdenken fällt mir immer noch etwas schwer. Naja, der Primer ist halt auch nur der Einstieg fürs C++ programmieren.
Danke auch für die anderen beiden Links. Werde mir das Ganze mal in Ruhe durchlesen.
Sebastian Pizer schrieb:
in welcher Hinsicht ist das übertrieben? Was genau meinst Du mit leichter?
Eine Klasse, die nur zwei abstrakte Methoden enthält empfand ich als etwas übertrieben. In diesem Fall finde ich eine Lösung mit einem Interface, das zwei abstrakte Methoden enthält, einfach eleganter. Aber ich kenne mich bei C++ ja nicht so gut aus, als dass ich mir hier anmuten würde zu sagen, dass man das in C++ nicht genauso gut implementieren kann

Ein Buch, das einem gutes Design lehrt, wäre wohl wirklich nicht schlecht. Ich bestelle mir das Effective C++ Buch mal.
Vielen Dank für deine ausgiebige Antwort.
-
icarus2 schrieb:
Eine Klasse, die nur zwei abstrakte Methoden enthält empfand ich als etwas übertrieben. In diesem Fall finde ich eine Lösung mit einem Interface, das zwei abstrakte Methoden enthält, einfach eleganter.
Hmmm und wo ist nun der Unterschied? Ob ich nun schreibe:
class Function { public: virtual bool validNrOfArguments(int count) = 0; virtual double calculate(double[] values) = 0; };Oder:
public interface Function { public boolean validNrOfArguments(int count); public double calculate(double[] values); }Ziemlich egal. Wenn es wirklich einen Unterschied gibt, dann wäre es eigentlich die Sache mit der Schattenklasse, was es in C++ nicht gibt. Allerdings ist es grundsätzlich auch nicht nötig, da man in C++ deutlich einfacher Callbacks erstellen kann. Was aber schlussendlich eben auch zu einem anderen Design führt

Grüssli
-
Naja, hast schon recht. Ist nicht wirklich ein Unterschied ^^