Argumentloser Konstruktor
-
@Th69 sagte in Argumentloser Konstruktor:
Bei der Kopie von A wird der (implizite) Kopierkonstruktor A(const A&) aufgerufen und an den Konstruktor übergeben.
Bei jedem Konstruktor, also auch bei
B::B(A a_) {
a = a_;
}
werden zuerst die Member default-initialisiert (bevor der Methodenblock ausgeführt wird),Bin mir nicht sicher, ob das nicht das ist, was ich sagte, wenn nicht gar widersprüchlich...
@NPC Nimm
B(A & a_)
und fertig. In den meisten Fällen möchte man das haben. Der Aufrufer muss sich dann aber darum kümmern.
-
@NoIDE sagte in Argumentloser Konstruktor:
@NPC Nimm B(A & a_) und fertig. In den meisten Fällen möchte man das haben
Naja, "meistens" will man ...
const A&
... mitconst
haben. Man muss aber in C++ schon immer wissen, was man tut, gerade was Ownership und Parameterübergabe angeht. Und man kann schlecht ohne genaue Kenntnis des Problems sagen "nimm A" oder "nimm B". Vielleicht will man eine Kopie machen, vielleicht sogar einenshared_ptr
nehmen, wer weiß.
-
@NoIDE Und fertig? Zeig mal, wie die kurze Klasse dann bei dir aussehen würde?
-
@NoIDE sagte in Argumentloser Konstruktor:
Bin mir nicht sicher, ob das nicht das ist, was ich sagte, wenn nicht gar widersprüchlich...
Es wird aber keine Instanz von A kopiert, sondern der Member wird initialisiert.
-
Wenn ich da jetzt etwas hin klatsche, von dem ich glaube, dass es richtig ist, da ich die genauen Anforderungen ja nicht kenne, dann ist ihm ja nicht weitergeholfen.
Ich denke, einige vergessen hier gerne, dass auch sie mal klein angefangen haben.
-
@NoIDE Nein, es geht darum, dass deine Empfehlung nicht einfach so funktioniert. Der TE hat ja ein Beispiel gepostet.
B::B(A& a_): { a = a_; }
geht nämlich nicht. Wenn der Member
a
eine Referenz ist, kann der nämlich nicht uninitialisiert sein.
-
@Schlangenmensch
Jo, das war mir bewusst. Wenn sich der Parameter zu Referenz ändert, dann muss das natürlich auch konsequent durchgezogen werden...
-
@NoIDE Ich glaube, du weißt nicht wo von ich Rede. "Verwende Referenz und dann geht das mit der Zuweisung im Ctor" ist schlicht falsch.
-
@Schlangenmensch sagte in Argumentloser Konstruktor:
"Verwende Referenz und dann geht das mit der Zuweisung im Ctor"
Den zweiten Teil dieses
GliedsatzesParataxes hab ich aber so nicht geschrieben.
-
@NoIDE sagte in Argumentloser Konstruktor:
@Schlangenmensch sagte in Argumentloser Konstruktor:
"Verwende Referenz und dann geht das mit der Zuweisung im Ctor"
Den zweiten Teil dieses
GliedsatzesParataxes hab ich aber so nicht geschrieben.Deswegen die Aufforderung, dass du konkret den Code schickst, den du hier für dieses konkrete Problem vorschlägst. Wenn du einfach nur sagst, macht XYZ (und sonst nix), dannm hast du eine Referenz mit Zuweisung im Ctor. Insofern doch, der zweite Teil war impliziert in deiner Aussage.
@NoIDE sagte in Argumentloser Konstruktor:
@Th69 sagte in Argumentloser Konstruktor:
Bei der Kopie von A wird der (implizite) Kopierkonstruktor A(const A&) aufgerufen und an den Konstruktor übergeben.
Bei jedem Konstruktor, also auch bei
B::B(A a_) {
a = a_;
}
werden zuerst die Member default-initialisiert (bevor der Methodenblock ausgeführt wird),Bin mir nicht sicher, ob das nicht das ist, was ich sagte, wenn nicht gar widersprüchlich...
@NPC Nimm
B(A & a_)
und fertig. In den meisten Fällen möchte man das haben. Der Aufrufer muss sich dann aber darum kümmern.Nein, es ist nicht das, was du sagtest. Du hast gesagt:
@NoIDE sagte in Argumentloser Konstruktor:
das heißt, jedes Mal, wenn eine Instanz von B erstellt wird, wird versucht, die Instanz von A zu kopieren, was aber scheitert, da A keinen parameterlosen Konstruktor hat.
Es stimmt, dass die Instanz von A kopiert wird (erster Teilsatz), aber es stimmt nicht, dass es daran scheitert (zweiter Teilsatz). Es scheitert daran, dass keine Initalisierungsliste verwendet wird. Im Gegensatz zu Java finden Member Initialisierungen dort statt. Hat man die nicht, wird das Objekt default initialisiert und dann fehlt der parameterlose Konstruktor.
Also nochmal zusammengefasst:
- Es liegt NICHT an der Übergabe per Value, es würde genauso auch bei einer Referenz scheitern
- Einen parameterlosen Konstruktur anzulegen "löst" das Problem insofern, dass dann die Fehlermeldung weg geht
- Die eigentliche Lösung ist aber eine Intialisierungsliste zu verwenden
- Übergabe an den Konstruktur per Kopie, Pointer, Referenz oder const Referenz hängt dann vom use case ab (d.h. Ownership Requirements, Semantik, Größe der Objekte etc.). Vor allem beim Konstruktor gibt es nicht die eine Art, die immer sinnvoll ist.
-
Ich hab aber noch eine Frage, das von dir beschriebene, "merkwürdige" Verhalten gilt aber nur bei Ctor-Aufrufen, oder?
-
@NoIDE sagte in Argumentloser Konstruktor:
Ich hab aber noch eine Frage, das von dir beschriebene, "merkwürdige" Verhalten gilt aber nur bei Ctor-Aufrufen, oder?
Ich weiß nicht, was du genau mit merkwürdigem Verhalten meinst? Das Problem hängt wie von mir beschrieben eben mit der Konstruktion des Objektes zusammen, daher tritt es also natürlich auch nur bei der Konstruktion von Objekten auf. Dort aber immer. Egal ob man jetzt den CTor explizit definiert oder nicht. Ich weiß aber nicht, was da genau merkwürdig sein soll.
Es ist vlt. merkwürdig aus Sicht eines Java Programmierers in folgender Hinsicht:
- In Java werden meines Wissens nach Felder (Members) erst initialisiert, nachdem der Body des Konstruktors ausgeführt wird. Eine Initialisierungsliste gibt es nicht. Bei C++ eben vor dem Body, dafür gibt es aber halt die Initialisierungsliste
- In Java hat man Referenztypen für Objekte (neben primitiven Datentypen) und deren Default Value ist null analog zu Pointern in C++ (nullptr). Bei der Default Initialisierung wird also nie ein Objekt konstruiert und entsprechend gibt es solch einen Fehler wie in C++ auch nicht in Java
In beiden Fällen ist es aber nicht merkwürdig, sondern eben unterschiedliches Sprachdesign und somit höchstens für den entsprechenden Programmierer unüblich, der es anders gewohnt ist.
-
@Leon0402 sagte in Argumentloser Konstruktor:
In Java werden meines Wissens nach Felder (Members) erst initialisiert, nachdem der Body des Konstruktors ausgeführt wird. Eine Initialisierungsliste gibt es nicht. Bei C++ eben vor dem Body, dafür gibt es aber halt die Initialisierungsliste
Hm, idR. beim Aufruf des ctors, oder sie sind static, dann bereits davor. Konstante (final) Felder müssen übrigens immer einen Wert haben, also entweder direkt bei der Deklaration oder sie werden im Ctor initialisiert.
@Leon0402 sagte in Argumentloser Konstruktor:
In Java hat man Referenztypen für Objekte (neben primitiven Datentypen) und deren Default Value ist null analog zu Pointern in C++ (nullptr). Bei der Default Initialisierung wird also nie ein Objekt konstruiert und entsprechend gibt es solch einen Fehler wie in C++ auch nicht in Java
Es gibt die Default-Initialisierung, ja. Aber im Unterschied zu C++ werden dabei keine neuen Instanzen erstellt (wenn man das nicht explizit angibt).
In Java gibt es keine Variablen (auch keine Member/Felder), die keinen Wert haben (uninitialisiert sind), wenn sie gelesen werden, das stellt der Compiler sicher.
Mir ist neu (war neu), dass in C++ die Member vor Aufruf des Ctors default initialisiert werden. In Java kann es keine Objekte geben, die nicht mit new/Ctor angelegt wurden. Das ist vermutlich der Unterschied.
-
Moin
Ja das ist unschön aber c++ verhält sich da korrekt. Mein Workaround: Lass den legacy Konstruktor einfach weg und erstelle eine custom Ersatzmethode in der Basisklasse und die wird ganz normal vererbt. Einziger Nachteil damit ist daß diese Methode extra aufgerufen werden muß.SubClass *res = new SubClass; // hier nichts übergeben res->inst(foo, bar); // rufe den Ersatzkonstruktor
MFG
-
Dann is es aber keine Komposition im UML-sinne mehr...
-
@nameName sagte in Argumentloser Konstruktor:
Dann is es aber keine Komposition im UML-sinne mehr...
Und wo war das gefordert? Egal, Hauptsache mal wieder nen Fachbegriff angebracht, um zeigen zu wollen, dass du Ahnung von iwas hast.
-
-
@DocShoe sagte in Argumentloser Konstruktor:
@nameName sagte in Argumentloser Konstruktor:
Dann is es aber keine Komposition im UML-sinne mehr...
Und wo war das gefordert? Egal, Hauptsache mal wieder nen Fachbegriff angebracht, um zeigen zu wollen, dass du Ahnung von iwas hast.
Das ist doch Nonsens. Ich habe mir lediglich die Mühe gemacht, und die Fragestellung genau gelesen. Ihr anscheinend nicht.
De-facto habt ihr die Komposition in eine Aggregation oder sogar nur in einfache Assoziation aufgeweicht. Die Ein-existentieller-Teil-eines-Ganzen-Beziehung besteht nicht mehr.
Und warum das Ganze? Weil nicht sein kann, was nicht sein darf: Meine Vorschläge waren womöglich richtig.
-
Dann zitier doch bitte mal den Aufgabentext, wo Komposition gefordert ist, ich finde da nix.
-
Es stimmt, dass das Wort "Komposition" nicht geschrieben steht oder gar gefordert wurde.
Aber wenn ich objektorientiert mit C++ arbeite, lassen Dinge wie "Referenz von einem Objekt auf ein anderes Objekt" oder "Objekt ist ein integraler Bestandteil eines anderen Objektes" eine gewisse Interpretation im UML-Sprachgebrauch zu.
Also aus dem zuerst gezeigten Quell-Kode geht schon hervor, dass Klasse "A" ein integraler Bestandteil von Klasse "B" ist, ergo diese Beziehung in UML als "Komposition" bezeichnet werden kann.
Die Bemerkung von @nameName ist so falsch also nicht.
Ob die Bezeichnung "Komposition" in Beziehung zur UML "Oldschool" ist, sei dahingestellt, dass ist u.a. "Mathematik" auchDiese Themen wurde in diesem Forum auch schon diskutiert, hier eine kleine Auswahl;
Aggregation und Komposition realisieren
Asossziation, Aggregation, Komposition - wie wird es realisiert
Wo liegt der Unterschied zw. Assoziation, Aggregation und Komposition?