Konstrukter Problem?
-
Probe-Nutzer schrieb:
Hallo,
ntfs2008 schrieb:
hustbaer schrieb:
dcomplex::dcomplex(double x){ re = 0; im = x; // <-- WTF??? cout << "\nObjekt erzeugt.\n"; }was stimmt daran nicht?
passt schon...
Nö! Woher soll der Anwender denn wissen, dass er den imaginärteil angibt, wenn er nur ein Parameter angibt? Dann mach wenigstens
dcomplex::dcomplex (const double &_im) : re (0), im (_im) {}Wobei ich diesen CTor einfach weglassen würde...
Übrigens würde ich davon abraten, die Variablenbez. in Headern wegzulassen, nur weil man nicht gezwungen wird, sie da hinzuschreiben... Im Header kann man viel schneller nachsehen, was für Variablen erwartet werden...
bb
-
Ich würde Parameterbezeichner grundsätzlich immer angeben, auch bei der Deklaration. Es ist dann einfach übersichtlicher, und man weiss, was für Argumente übergeben werden müssen, und nicht nur, von welchem Typ sie sein müssen.
hustbaer schrieb:
Genau so wie du bei der Definition einen Bezeichner für den Parameter angeben musst (wie in jeder Funktion).
Nö, nur wenn man den/die Parameter auch verwenden will
Danke für die Berichtigung. Aber es wird sowieso in 99% der Fälle so sein, dass man die Argumente innerhalb der Funktion benötigt.
-
unskilled schrieb:
Probe-Nutzer schrieb:
Hallo,
ntfs2008 schrieb:
hustbaer schrieb:
dcomplex::dcomplex(double x){ re = 0; im = x; // <-- WTF??? cout << "\nObjekt erzeugt.\n"; }was stimmt daran nicht?
passt schon...
Nö! Woher soll der Anwender denn wissen, dass er den imaginärteil angibt, wenn er nur ein Parameter angibt?
Hi also wenn man nur eine Zahl angibt dann ist es doch wohl klar das dies nur der imaginäre Teil ist. Wenns andersrum wäre dann bräuchte ich doch wohl kaum komplexe Zahlen. Es würden dann ja einfache reelle reichen.
[quote="unskilled"]
Probe-Nutzer schrieb:
Dann mach wenigstens
dcomplex::dcomplex (const double &_im) : re (0), im (_im) {}Wobei ich diesen CTor einfach weglassen würde...
Was macht der obrige Code? Da kann ich absolut nichts mit anfangen.
Zudem: Was ist ein CTOR? Konstruktor oder wie?[quote="unskilled"]
Probe-Nutzer schrieb:
Übrigens würde ich davon abraten, die Variablenbez. in Headern wegzulassen, nur weil man nicht gezwungen wird, sie da hinzuschreiben... Im Header kann man viel schneller nachsehen, was für Variablen erwartet werden...
bb
Klingt absolut logisch! Wird ab jetzt beherzigt! Danke
Gruß Timo
-
ntfs2008 schrieb:
...
Hi also wenn man nur eine Zahl angibt dann ist es doch wohl klar das dies nur der imaginäre Teil ist....Also mir begegnet dieser Schluss zum ersten Mal.
Da habe ich sogar den gegenteiligen Schluss ("Wenn nur ein Argument, dann ist doch klar, dass es nur der Realteil ist!") sowohl öfter begegnet als auch ein wenig schlüssiger (was nicht bedeuten soll, dass ich das so machen würde!).Was würdest Du denn erwarten bei:
double real = 1.2; dcomplex compl; compl = real;Würdest Du da auch erwarten, dass compl rein imaginär wäre ?
OK, den operator=(double) musst Du nicht (so) implementieren, aber semantisch ist er seeeehr nah am Ctor(double), z.B: in:void do_with_complex(dcomplex d); int main() { double real = 1.2; do_with_complex(real); ...unskilled schrieb:
Probe-Nutzer schrieb:
Hallo,
ntfs2008 schrieb:
hustbaer schrieb:
dcomplex::dcomplex(double x){ re = 0; im = x; // <-- WTF??? cout << "\nObjekt erzeugt.\n"; }was stimmt daran nicht?
passt schon...
Nö! Woher soll der Anwender denn wissen, dass er den imaginärteil angibt, wenn er nur ein Parameter angibt? ...
sowas macht z.B. folgendermaßen Probleme:
dcomplex a1(1,2), a2(3.4), a3(5,6);Na ? War das wirklich das, was der Programmierer wollte ?
Insgesamt muss man sehr vorsichtig sein mit solchen "Konvertierungstoren" (Ctor wenigstens "explicit" machen)...Gruß,
Simon2.
-
Wenn man die Parameterbezeichner richtig benennt (und "x" ist meines Erachtens kein aussagekräftiger Bezeichner), kann man auch folgendes tun:
dcomplex::dcomplex(double real = 0, double imag = 0) : re(real) , im(imag) { }Dann hat man auch gleich für einen Default-Ctor gesorgt. Den Zuweisungsoperator müsste man in diesem Fall angleichen, um die gleiche Semantik für 1 Argument zu erzielen.
Es ist wohl naheliegender, den Realteil zu spezifizieren, wenn man nur ein Argument übergibt.
dcomplex c = 4; // rechts steht der Wert 4, wieso sollte // links danach nicht auch den selben Wert haben?Oder, um ganz sicher zu sein, kann man es wie Simon2 machen: Konstruktor explizit und ohne Defaultparameter (man muss so auch ausdrücklich angeben, dass der Imaginärteil 0 ist, wenn man eine rein reelle komplexe Zahl will).
-
Nexus schrieb:
...
Es ist wohl naheliegender, den Realteil zu spezifizieren, wenn man nur ein Argument übergibt...
@ntfs: siehste ? :p

Gruß,
Simon2.
-
unskilled schrieb:
Nö! Woher soll der Anwender denn wissen, dass er den imaginärteil angibt, wenn er nur ein Parameter angibt?
Und woher soll ntfs2008 wissen, dass das gemeint ist?
ntfs2008 hatte eventuell andere Bedenken, als er sich wunderte, warum der Kommentar da steht.
Da, wo der Kommentar steht, gilt also "passt schon", nichts anderes war gemeint, wenn auch noch mehr dazu zu sagen gewesen wäre:
Passendere Anmerkung wäre also gewesen: warum nur ein solcher Konstruktor, warum dann nicht auch einer, der nur den Realteil initialisiert, warum überhaupt dieser Konstruktor, oder...
Ich dachte mir auch, dass dies der Grund ist, aber dann bitte doch explizit und nicht implizit, so hilft das auch nicht so versierten Leuten.
MfG,
Probe-Nutzer
-
Probe-Nutzer schrieb:
...
Und woher soll ntfs2008 wissen, dass das gemeint ist?...Da verteigst Du wohl löblich und vehement eine leere Schachtel:
ntfs2008 schrieb:
...also wenn man nur eine Zahl angibt dann ist es doch wohl klar das dies nur der imaginäre Teil ist....
Es war wohl tatsächlich eine bewusste Designentscheidung.
Gruß,
Simon2.
-
Simon2 schrieb:
ntfs2008 schrieb:
...
Hi also wenn man nur eine Zahl angibt dann ist es doch wohl klar das dies nur der imaginäre Teil ist....Also mir begegnet dieser Schluss zum ersten Mal.
Da habe ich sogar den gegenteiligen Schluss ("Wenn nur ein Argument, dann ist doch klar, dass es nur der Realteil ist!") sowohl öfter begegnet als auch ein wenig schlüssiger (was nicht bedeuten soll, dass ich das so machen würde!).Was würdest Du denn erwarten bei:
double real = 1.2; dcomplex compl; compl = real;Wie soll das gehen? compl hat doch den Datentyp dcomplex und real den Datentyp double. Da muss man doch zunächst den operator = überladen oder wie ist das?
Also man muss zunächst einmal bedenken wofür wir die komplexe Rechnung überhaupt benötigen. Warum sollte ich eine reelle Zahl als komplexe Darstellen wollen? Das ist doch absolut unlogisch und auch irgendwie nicht naturgemäß.
Ein wichtiges Anwendungsgebiet ist hier die Elektrotechnik. Widerstände sind hier rein reell, Spulen und Kondensatoren sind rein imaginär. Da liegt es doch auf der Hand Resistanzen als double oder float zu deklarieren und Impedanzen und Admitanzen als komplexe. Die Summe daraus ergibt logischerweise natürlich wieder eine komplexe Zahl. Aber wie und was gerechnet werden soll dass muss ich doch in meinen Methoden und Überladungen beschreiben.
Also ich habe mich ein komplettes Semester mit der komplexen Rechnung in allen erdenklichen Variationen rumschlagen müssen und bin mir sicher, dass dies auch im Programm richtig umgesetzt wurde.
Es gibt einfach nur rein reelle (double), rein imaginäre (dcomplex) und komplexe (dkomplex) Objekte.Simon2 schrieb:
sowas macht z.B. folgendermaßen Probleme:
dcomplex a1(1,2), a2(3.4), a3(5,6);Na ? War das wirklich das, was der Programmierer wollte ?
Insgesamt muss man sehr vorsichtig sein mit solchen "Konvertierungstoren" (Ctor wenigstens "explicit" machen)...Gruß,
Simon2.
Ne ganz bestimmt nicht. Aber das selbe Problem hast du doch auch, wenn du den Wert dem Realteil zuweist...
-
ntfs2008 schrieb:
Warum sollte ich eine reelle Zahl als komplexe Darstellen wollen? Das ist doch absolut unlogisch und auch irgendwie nicht naturgemäß.
Die scheint entgangen zu sein, dass sich jede reelle Zahl auch als komplexe Zahl mit dem Imaginärteil 0 darstellen lässt. Genauso wie sich jede natürliche Zahl auch als reelle Zahl ohne Brüche darstellen lässt. Darüberhinaus könnte sogar mal jemand mit komplexen Zahlen rechnen wollen, wobei eine dieser komplexen Zahlen den Imaginärteil 0 haben könnte.
Anders ausgedrückt: Da die Menge der reellen Zahlen vollständig in der Menge der komplexen Zahlen enthalten ist, wieso sollte man dem Benutzer verbieten, eine reelle Zahl als komplexe Zahl darzustellen?
-
LordJaxom schrieb:
Die scheint entgangen zu sein, dass sich jede reelle Zahl auch als komplexe Zahl mit dem Imaginärteil 0 darstellen lässt...
Was soll der bescheuerte Spruch denn jetzt?
Ja lasst uns einfach alle irgendwelche unqualifizierten Sprüche an den Kopf werfen...Ja natürlich kann man eine reelle Zahl auch als komplexe Zahl darstellen.
Nur macht das doch absolut keinen praktischen Sinn.
Also die Verfechter der "Bei der Übergabe von einem Parameter muss damit der Realteil initalisiert werden." sind im Grunde immer noch einer nachvollziehbaren Erklärung schuldig.
Außer "ist doch viel sinniger..." habe ich noch nix gehört.
Zudem verbiete ich dem Anwender ja nichts.Ich gehe einfach nur davon aus, dass der Anwender sich mit der komplexen Rechnung auskennt. Somit sind Fragen "warum denn nun der imaginäre Teil initalisiert wird" völlig egal. Es gilt hier Netzwerke aus Resistanzen und Reaktanzen (bzw. Impedanzen) zu berechnen. Da hat man eben nur Widerstände (rein reell), und Spulen und Kondensatoren, entweder rein imaginär (idialisiert), oder ganz normal komplex bei realen Bauteilen.
Das sollte jetzt auch mal reichen. Schließlich ist das hier ein Forum für Programmierfragen und kein Forum für Mathe.
Nichts für ungut.
Grüße Timo
-
doch in diesem forum gibt es auch einen Teil für mathe^^

-
ntfs2008 schrieb:
Was soll der bescheuerte Spruch denn jetzt?
Ja lasst uns einfach alle irgendwelche unqualifizierten Sprüche an den Kopf werfen...So bescheuert du den Spruch auch finden magst, LordJaxom hat damit Recht.
ntfs2008 schrieb:
Ja natürlich kann man eine reelle Zahl auch als komplexe Zahl darstellen.
Nur macht das doch absolut keinen praktischen Sinn.Ich hab das Gefühl, du siehst das Ganze ein wenig zu engstirnig, nämlich nur aus der Sicht für Elektrotechnik. Wenn du aber eine Klasse für komplexe Zahlen entwickeln willst, denken die meisten an komplexe Zahlen, wie sie in der Mathematik (ja, auch wenn das nicht das Mathe-Unterforum ist) definiert sind. Wenn du sie nur für Elektrotechnik benötigen würdest, müsstest du die Klasse vielleicht ein bisschen einschränken, und vor allem nicht als Klasse für komplexe Zahlen ausgeben. Denn eine solche sollte meiner Ansicht nach schon die Rechengesetze erfüllen.
ntfs2008 schrieb:
Also die Verfechter der "Bei der Übergabe von einem Parameter muss damit der Realteil initalisiert werden." sind im Grunde immer noch einer nachvollziehbaren Erklärung schuldig.
Also, ich versuch es mal.
Du hast folgendes:
int i = 55; double d = i; // Hier ist zu erwarten, dass d nachher den (reellen) Wert 55 hat. char c = i; // Hier ebenfalls.Nun machen wir das Gleiche mit der Klasse für komplexe Zahlen:
dcomplex o = i;Von komplexen Zahlen wird erwartet, dass sie auch mit (rein) reellen Zahlen umgehen können. Da die reellen Zahlen wie gesagt eine Teilmenge der komplexen Zahlen sind, ist eine reelle Zahl auch als komplexe darstellbar. Also sollte man einer komplexen Zahl auch eine reelle zuweisen können (gleiches gilt für die Initialisierung im Konstruktor). Was läge also näher, als wenn diese Operation:
dcomplex o = i;zur Folge hätte, dass der komplexen Zahl o der Wert der reellen Zahl i zugeordnet würde? Dann würden beide Seiten für das Gleiche stehen. Welchen Sinn hätte es, wenn jetzt plötzlich der imaginäre Teil von o, der auf der rechten Seite gar noch nicht vorhanden ist, initialisiert wird, während der reelle Teil unbehandelt bleibt?
Abgesehen davon führt das zu viel weniger Missverständnissen, da das viel eher der erwarteten Funktionalität entspricht. Von einer Zuweisung wird meistens erwartet, dass eben ein Wert zugewiesen wird, sodass nachher beide Seiten den gleichen Wert (zumindest soweit als möglich) repräsentieren.
ntfs2008 schrieb:
Zudem verbiete ich dem Anwender ja nichts.
Doch, du erlaubst ihm nicht, eine Zuweisung so durchzuführen, dass der linke Teil (Lvalue) anschliessend den gleichen Wert hat wie der rechte (Rvalue), obwohl es möglich wäre.
ntfs2008 schrieb:
Ich gehe einfach nur davon aus, dass der Anwender sich mit der komplexen Rechnung auskennt. Somit sind Fragen "warum denn nun der imaginäre Teil initalisiert wird" völlig egal.
Nein, eben nicht, weil es 1. keine sinnvolle Zuweisung ist und 2. nicht das erwartete ist. Wenn mindestens die Parameternamen passender gewählt wären und vielleicht noch ein Kommentar vorhanden wäre, gäbe es womöglich schon viel weniger Probleme. Dennoch würde ich davon abraten.
ntfs2008 schrieb:
Nichts für ungut.
Ebenfalls. Ich hoffe, du verstehst mich nicht falsch und fasst das nicht als böse gemeint auf. Ich versuche nur zu helfen.
-
ntfs2008 schrieb:
Also die Verfechter der "Bei der Übergabe von einem Parameter muss damit der Realteil initalisiert werden." sind im Grunde immer noch einer nachvollziehbaren Erklärung schuldig.
Außer "ist doch viel sinniger..." habe ich noch nix gehört.Dann hast Du nach dem bescheuerten Spruch aufgehört zu lesen.
Aber um - neben von Nexus gesagtem - auch noch ein C++-Argument zu bringen:
Solange Dein Konstruktor nicht explicit ist, ist er für Konvertierungen geeignet. Das ist nichts schlechtes, im Gegenteil erleichtert das das natürliche Rechnen mit der Klasse und eingebauten Zahlentypen. Damit, und Deiner Initialisierung des Imaginärteils passiert aber nun folgendes (vorausgesetzt Du hast genau einen operator== für dcomplex,dcomplex):double d = 15.0; // 15.0 in R dcomplex c = d; // 0+15.0i in C // Mit explizitem Ctor müsste man folgendes schreiben, was nach meiner Erwartung aber nicht unbedingt etwas anderes liefern sollte // dcomplex c( d ); ( d == c ) // ist true, da d wie bei der Initialisierung in dcomplex umgewandelt wird, bevor zwei dcomplex miteinander verglichen werden // auch hier verlangt mein natürliches Leseverständnis, dass 15.0 nicht gleich 0+15.0i ist...
-
ntfs2008 schrieb:
...
Ne ganz bestimmt nicht. Aber das selbe Problem hast du doch auch, wenn du den Wert dem Realteil zuweist...Eben!
Deswegen würde ich eben diesen dcomplex(double) gar nicht deklarieren!
Darauf wollte ich ja hinaus.ntfs2008 schrieb:
...
Wie soll das gehen? compl hat doch den Datentyp dcomplex und real den Datentyp double. Da muss man doch zunächst den operator = überladen oder wie ist das?...Du solltest nicht vergessen, dass es Deine Idee war, ein doubles einem dcomplex zuzuweisen (denn genau diesen Wunsch drückt der dcomplex(double)-Konstruktor aus - dass Du den operator=(double) vergessen hast, liegt vermutlich daran, dass Du noch nicht sooo viel Erfahrung mit C++ hast). Oben hast Du noch geschrieben, dass es Dir vollkommen einleuchtend sei, dass man damit den Imaginärteil festlegen will ...
So eine "implizite Typkonvertierung" ist eigentlich gar nicht sooo abwegig, denn:
1.) Fachlich: Jede reelle Zahl ist auch Bestandteil der Menge der komplexen Zahlen. (das spräche aber eher für eine Zuweisung des Realteils)
2.) Man hat sich ja auch sowas angewöhnt:double i = 2; string s = "Simon2"; // auch eine implizite Konvertierung; hier (char const*) - std::string // ... oder mit operator=() i = 3; s = "ntfs2008";Wegen der o.g. Doppeldeutigkeit würde ich es eben besser ganz sein lassen.
(Alternative: Nur explicit-Konstruktor, der den Realteil mit dem Argument zuweist und den Imaginärteil mit 0 initialisiert)Gruß,
Simon2.