Standardkonstrukor



  • Hallo zusammen,
    ich wollte meinen Konstruktor mit Standardwerten versehen.

    Normalerweise macht man das ja so:

    Box (int w=1, int l=1, int h =1):m_width(w), m_height(h), m_length(l){}
    

    Dieses Wissen wollte ich auch hier anwenden:

    WordSequence::WordSequence(const std::string* words, const int& size):words(words),size(size){} //Konstruktor
    

    Allerdings bekomme ich diesen nicht zum laufen. Ich habe es so versucht:

    WordSequence::WordSequence(const std::string* words= "   ", const int& size=0):words(words),size(size){} //Konstruktor
    

    Funktioniert aber nicht. kann mir da jemand weiterhelfen?



  • @Johnny01 sagte in Standardkonstrukor:

    const std::string* words= " ",

    Du scheinst einen Pointer auf einen konstanten String zu erwarten, aber gibst " " als default an. Du könntest nullptr als Default angeben - oder soll dein words nicht vielleicht const std::string& (ohne *, ggf. mit &) sein?


  • Mod

    Klingt suspekt und C-artig mit den Pointern und der size. Du brauchst eine Initializer Liste!



  • @SeppJ habe doch eine Initializer Liste drin, ich wollte lediglich nur Default-Werte deklarieren



  • @Johnny01 sagte in Standardkonstrukor:

    @SeppJ habe doch eine Initializer Liste drin, ich wollte lediglich nur Default-Werte deklarieren

    Gemeint war eine https://en.cppreference.com/w/cpp/utility/initializer_list

    Die Frage ist allgemein, was dein WordSquence tut. Ist das wirklich ein Pointer auf String (der für Arrays von Strings genutzt wird)? Dann muss dein Default-Wert natürlich auch von demselben Typ sein, und nullptr wäre ein gangbarer Default. Die Frage ist eher, ob deine Klasse WordSequence so überhaupt sinnvoll ist.



  • @Johnny01 sagte in Standardkonstrukor:

    Normalerweise macht man das ja so:

    Box (int w=1, int l=1, int h =1):m_width(w), m_height(h), m_length(l){}
    

    Nein, so macht man das normerlweise eben nicht. Durch die Defaultargumente hat man hier ein Conversion Operator definiert mit dem sich int in Boxumwandeln lässt. Sinnvoller ist dann folgende Variante

    Box() : m_width(1), m_height(1), m_length(1) {}
    Box(const int w, const int h, const int l) : m_width(w), m_height(h), m_length(l){}
    


  • Oder mittels explicit unterbinden:

    explicit Box (int w=1, int l=1, int h =1):m_width(w), m_height(h), m_length(l){}
    

    Ideone-Beispiel

    @john-0: Außerdem kann man bei deinem Code nicht z.B. den letzten Wert weglassen: Box box(2, 3).


  • Mod

    @john-0 const int Parameter? 😂



  • @Th69 sagte in Standardkonstrukor:

    @john-0: Außerdem kann man bei deinem Code nicht z.B. den letzten Wert weglassen: Box box(2, 3).

    Wie sinnvoll ist das? Meistens braucht man einen Default Constructor und einen Constructor, der das Objekt sinnvoll konstruiert.

    @Columbo War ja klar, dass du das Konzept Kontrakte nicht verstehst.


  • Mod

    @john-0 Das Internet ist überwiegend meiner Meinung, dass const aus deklarativer Sicht vollkommen überflüssig ist, weil jeder Programmierer bestens weiss, wie by-value funktioniert. Bspw hier.

    Never use const in a function prototype for a parameter passed by value. It has no meaning and is hence just 'noise'.

    Und auch hier oder hier.

    Du kannst Dich gerne trotzdem austoben und uns erklaeren, warum Du Recht hast.


    Uebrigens waere const hier auch in einer getrennten Definition überflüssig, weil der ctor so prägnant ist, dass es keine 'Gefahr' gibt, dass die Parametervariable versehentlich geändert wird. (Das waere der hier genannte Anreiz fuer const.)

    Dogmatisch jedes einzelne Objekt const zu markieren macht den Code IMHO unleserlich und hat kaum Mehrwert. Vielleicht haben @SeppJ / @Th69 dazu noch eine Meinung.



  • @Columbo sagte in Standardkonstrukor:

    unleserlich

    Und vor allem inkonsistent, weil das niemand macht. Misch-masch ist immer störend und den hast du so halt fast sicher (durch 3rd libs, stl oder andere Programmierer)



  • Also ich mach lokale Variablen fast immer const.
    In ner 3-zeiler Funktion is das eher weniger interessant. In ner 30-Zeiler Funktion schon.
    Wobei es mit nicht darum geht dass ich aus versehen die Variablen ändern könnte. Sondern darum dass ich beim nächsten Mal wo ich den Code lese auch sofort sehe dass die Variable nicht geändert wird.

    Bei Parametern von längeren Funktionen greift grundsätzlich natürlich die selbe Logik. Allerdings kann ich mich da einfach nicht dazu überwinden - es sieht für mich einfach so dämlich aus 🙂

    Und dazu kommt noch: eines unserer Tools ist so dämlich, dass es nicht versteht dass top-level const in der Deklaration und Definition nicht zusammenstimmen muss. Und moppet dann rum wenn man es halt doch unterschiedlich macht. D.h. wenn ich die Variable bei der Definition const haben will, dann müsste ich sie auch bei der Deklaration const machen. Und das finde ich dann wirklich sehr doof.



  • Die Gründe, die für const-By-Value-Parameter sprechen, sind m.E. überzeugend genug um deswegen keine allzu große Diskussion vom Zaun brechen zu müssen oder das gar als eine Art Code Smell anzusehen. Sie helfen, die beabsichtigte Verwendung als nicht-mutable Eingabewerte zu dokumentieren und vermeiden Fehler wie versehentliche Zuweisungen, z.B. durch = vs. ==-Tippfehler.

    @hustbaer sagte in Standardkonstrukor:

    Bei Parametern von längeren Funktionen greift grundsätzlich natürlich die selbe Logik. Allerdings kann ich mich da einfach nicht dazu überwinden - es sieht für mich einfach so dämlich aus 🙂

    Allerdings schliesse ich mich auch hier der Meinung an, dass das zusätzliche Schlüsselwort für mehr Code-Rauschen sorgt und das Lesen erschwert. Auch ich finde, dass das irgendwie "komisch" aussieht und mache das vor allem deswegen (und wegen der extra Tipparbeit) ebenfalls nicht durchgängig.

    Kein Problem hätte ich allerdings damit, wenn in einer Sprache Parameter per Default const wären und man wie z.B. in Rust ein Keyword wie mut benötigt, wenn man eine modifizierbare Variable haben möchte (das wird es natürlich in C++ nicht mehr geben) - im Gegenteil, das halte ich sogar für einen guten Ansatz.

    Funktions-Inputs selbst werden in den meisten Fällen ohnehin nicht verändert (zumindest in dem Code mit dem ich arbeite). Ich finde es sogar eher schlechten Stil, wenn man direkt auf den Parameter-Variablen arbeitet anstatt auf einer dedizierten lokalen Variablen, in der man den Rückgabewert berechnet.



  • Mit dem top-level const mag jeder halten, wie er/sie/es mag.

    Nur die Aussage von @john-0 bzgl. Nichtverwendung von Defaultparametern kann ich nicht nachvollziehen.
    Es gibt Konstruktoren (und Funktionen) mit viel mehr Parametern und warum sollen dann beim Aufruf immer alle angegeben werden müssen?

    Und gerade bei

    Box() : m_width(1), m_height(1), m_length(1) {}
    Box(const int w, const int h, const int l) : m_width(w), m_height(h), m_length(l){}
    

    sehe ich das als unnötig an, wenn beide Konstruktoren quasi dasselbe machen (unnötige Codeduplizierung). Machst du das auch bei mehr als 3 Parametern?



  • @Finnegan
    Ja, ich denke es ist ziemlich klar dass - aus heutiger Sicht - C++ hier den falschen Default hat. Default sollte mMn. const sein. Bei Membervariablen könnte es etwas lästig werden, aber an so ziemlich allen anderen Stellen wäre default = const mMn. besser. Und ich hätte auch kein echtes Problem damit wenn man sogar Membervariablen extra markieren müsste damit man sie ändern kann.


  • Mod

    @Finnegan sagte in Standardkonstrukor:

    Die Gründe, die für const-By-Value-Parameter sprechen, sind m.E. überzeugend genug um deswegen keine allzu große Diskussion vom Zaun brechen zu müssen oder das gar als eine Art Code Smell anzusehen.

    Das war auch nicht der Diskussionspunkt. Er hat suggeriert, const soll bei der Deklaration schon im Parameter stehen, weil "Kontrakte".

    Ich hatte niemals angedeutet, dass const bei der Funktionsdefinition nicht sinnvoll sein kann, nur dass es bei sehr kurzen Definitionen einfach überflüssig ist (sowie const prinzipiell überflüssig ist, wenn die betroffene Variable sowieso nur einmal verwendet wird (Edit: ok, jetzt kommen gleich wieder irgendwelche kuenstlichen Gegenbeispiele...)).



  • @Columbo sagte in Standardkonstrukor:

    @Finnegan sagte in Standardkonstrukor:

    Die Gründe, die für const-By-Value-Parameter sprechen, sind m.E. überzeugend genug um deswegen keine allzu große Diskussion vom Zaun brechen zu müssen oder das gar als eine Art Code Smell anzusehen.

    Das war auch nicht der Diskussionspunkt. Er hat suggeriert, const soll bei der Deklaration schon im Parameter stehen, weil "Kontrakte".

    Ja, das war mir nicht ganz klar. Bei By-Value-Variablen erachte ich das const auch als eine funktionsinterne Information und finde es auch überflüssig und sogar störend, wenn das im Interface mitkommuniziert wird (Mit er Einführung von Modules frage ich mich aber auch ob separate Deklarationen und Definitionen irgendwann überhaupt noch angesagt sind, wenn man nicht unbedingt eine Forward-Deklaration braucht - ist ja schon extra Aufwand).

    Ich hatte niemals angedeutet, dass const bei der Funktionsdefinition nicht sinnvoll sein kann, nur dass es bei sehr kurzen Definitionen einfach überflüssig ist

    Zur Kenntnis genommen 😉

    (sowie const prinzipiell überflüssig ist, wenn die betroffene Variable sowieso nur einmal verwendet wird (Edit: ok, jetzt kommen gleich wieder irgendwelche kuenstlichen Gegenbeispiele...)).

    Wenn du schon drum bettelst:

    auto quadriere(const int n) {
        return n * n;
    }
    

    😝



  • @Finnegan sagte in Standardkonstrukor:

    (sowie const prinzipiell überflüssig ist, wenn die betroffene Variable sowieso nur einmal verwendet wird (Edit: ok, jetzt kommen gleich wieder irgendwelche kuenstlichen Gegenbeispiele...)).

    Wenn du schon drum bettelst:

    auto quadriere(const int n) {
        return n * n;
    }
    

    😝

    Wieso sollte const hier nicht überflüssig sein?



  • @hustbaer sagte in Standardkonstrukor:

    Wieso sollte const hier nicht überflüssig sein?

    Es ging mir um ein möglichst leichtgewichtiges Trollbeispiel, in dem die Parameter-Variable eben nicht "nur einmal" (wie @Columbo schrieb) verwendet wird. Daher auch der Smiley mit rausgestreckter Zunge 😁



  • @Th69 sagte in Standardkonstrukor:

    Mit dem top-level const mag jeder halten, wie er/sie/es mag.

    Nur die Aussage von @john-0 bzgl. Nichtverwendung von Defaultparametern kann ich nicht nachvollziehen.
    Es gibt Konstruktoren (und Funktionen) mit viel mehr Parametern und warum sollen dann beim Aufruf immer alle angegeben werden müssen?

    Dann reden wir über andere Funktionsdeklarationen, und dann ist im konkreten Fall zu beurteilen, ob das sinnvoll ist oder nicht.

    Und gerade bei

    Box() : m_width(1), m_height(1), m_length(1) {}
    Box(const int w, const int h, const int l) : m_width(w), m_height(h), m_length(l){}
    

    sehe ich das als unnötig an, wenn beide Konstruktoren quasi dasselbe machen (unnötige Codeduplizierung).

    In der Schnelle habe ich keine Konstruktor Delegation genutzt. Aber Mikrooptimierungen sind Dinge, die man gleich ganz unterlassen sollte, sprich ob das nun Codeduplizierung ist, ist an dieser Stelle relativ egal, und bei umfangreicheren Konstruktoren nutzt man Konstruktor Delegation.

    Box (const int w, const int h, const int l) : m_width(w), m_height(h), m_length(l) {}
    Box () : Box (1, 1, 1) {}
    

    Machst du das auch bei mehr als 3 Parametern?

    Das kommt auf den Konstruktor an. Die Frage ist, wie man sinnvoll ein Objekt konstruiert. Es mag bei C++ zuweilen gute Gründe geben einen Defaultkonstruktor zu definieren, auch wenn das aus der Logik der Objekte sich nicht unbedingt ergibt.

    Aber, wie sinnvoll ist es bei einem Quader nicht alle drei Dimensionen anzugeben?

    @Columbo sagte in Standardkonstrukor:

    @john-0 Das Internet ist überwiegend meiner Meinung, dass const aus deklarativer Sicht vollkommen überflüssig ist, weil jeder Programmierer bestens weiss, wie by-value funktioniert.

    Es ist nicht überflüssig, es ist vielleicht nicht notwendig. Es richtet vor allem keinen Schaden an. Es geht darum glasklar zu dokumentieren, was da gemacht wird. Es mag Dir immer klar sein, dass in C++ die Parameterübergabe by Value erfolgt. Ich programmiere aber nicht nur in einer Sprache, und der Code wird nicht nur von Personen gelesen, die jeden Tag ausschließlich C++ nutzen. Weißt Du von jeder von Dir jemals genutzten Sprache (ohne vorher nachzuschauen) wie die Parameterübergabe funktioniert?

    Es geht darum Code so zu schreiben, dass er auch noch in Jahren leicht gewartet werden kann, und man vorher nicht erst etliche Dokumentationen durcharbeiten muss.

    Es geht nicht darum zu zeigen, was für ein toller Hecht man als Programmierer ist. Was ich an dir problematisch erachte, ist nicht, dass du das anders machst, sondern, dass du dich zu überheblichen Kommentaren hinreißen lässt. Das tun meiner Erfahrung nach nur Personen, die von den Defiziten ihrer eigenen Arbeit ablenken wollen.


Anmelden zum Antworten