Argumentloser Konstruktor



  • Hi @Th69,

    a soll nicht unabhängig von a_ arbeiten. D.h., wenn ich dich richtig verstehe, eine übergabe als Referenz oder Zeiger ist ok.

    Mit Initialisierungslisten werde ich mich dann jetzt wohl mal beschäftigen xD.

    Viele Grüße
    NPC



  • Hi @Schlangenmensch,

    d.h., dass das Objekt exponentiell mit einem Parameter wächst. Die konkrete Basis ist abhängig von einem anderen Parameter und spielt eigentlich auch keine Rolle. Das Objekt wird am Ende gut und gerne 20-30 Gb groß (Es liegt sehr nah an einem auf einem Blatt errechneten Mindestgröße die aus dem Problem selbst folgt). Dabei arbeitet A im wesentlichen als, schon komprimierter [wieder auf dem Blatt], Container.

    Leider muss ich mich, der Aufgabe wegen, hier auf die Performance fokusieren.
    Die Frage die sich sofort stellt ist natürlich die wie sehr ich auf Performance schauen kann, wenn mir dergleichen Eigenschaften unbekannt sind. Das ist (hoffentlich) weniger kritisch als es scheint. Mein Ursprüngliches Problem lag an einer misinterpretation der Übergabe selbst. Mir war nicht bewusst, dass ich nicht automatisch einen Pointer übergebe, wenn ich ein Objekt übergeben will. Da bin ich wohl aus anderen Programmiersprachen zu sehr verwöhnt.

    Viele Grüße
    NPC



  • @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&... mit const 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 einen shared_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 Gliedsatzes Parataxes 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 Gliedsatzes Parataxes 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.


  • @Leon0402
    💯

    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:

    @Leon0402
    💯

    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


  • Gesperrt

    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.



  • @nameName

    das vielleicht nicht aber Oldschool 😉

    FF


  • Gesperrt

    @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. 🤭


Anmelden zum Antworten