Standardkonstrukor



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



  • @john-0 sagte in Standardkonstrukor:

    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

    😀

    Mehr Glashäuser und Steine hab ich wohl noch nie gesehen....


  • Mod

    @john-0 sagte in Standardkonstrukor:

    @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?

    Hoer auf mit non sequiturs um dich zu werfen, um deine Totgeburt von einem Standpunkt zu verteidigen.
    Was haben andere Sprachen mit C++ zu tun?
    Warum sollte ich jemals eine C++ Datei oeffnen und ploetzlich das komplette Typsystem verwechseln, so als ob ein int Parameter eine Referenz ist?
    Warum sollten meine Kollegen, nur weil sie nicht "ausschliesslich C++" programmieren, so dermassen ignorant sein, dass sie nicht einmal die Grundsaeule des Typsystems verinnerlicht haben?
    Warum vertrittst Du in einem Expertenforum ein Paradigma, dass scheinbar fuer Zusammenarbeit mit absoluten Noobs konzipiert ist?

    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.

    Hast Du Angst, in ein paar Jahren zu vergessen, wie Parameteruebergabe in C++ funktioniert?

    Es geht nicht darum zu zeigen, was für ein toller Hecht man als Programmierer ist.

    Du musst schon prophylaktisch deine Parameter const markieren weil Du Java nicht von C++ unterscheiden kannst... Du bist eher ein Seestern.

    Edit: Das ist ein schlechtes Beispiel, weil Java fundamentale Typen nicht by-reference behandelt. Ich kann mir auf die schnelle tatsaechlich keine Beispielsprache ueberlegen, wo int standardmaessig eine Referenz ist.. was wiederum die Validitaet deines Arguments unterminiert...



  • @Columbo sagte in Standardkonstrukor:

    Warum vertrittst Du in einem Expertenforum ein Paradigma, dass scheinbar fuer Zusammenarbeit mit absoluten Noobs konzipiert ist?

    "in einem Expertenforum"? Die meisten Threads hier werden von Personen eröffnet, die gerade dabei sind, Grundlagen zu lernen.

    Außerdem: was ist schlecht daran, wenn Code auch von absoluten Noobs gelesen werden kann. Nur weil Code nicht von Noobs gelesen werden kann, ist er nicht deswegen besser (natürlich gibt es Fälle, wo der nicht-Noob-kompatible Code besser ist).

    Warum sollten meine Kollegen, nur weil sie nicht "ausschliesslich C++" programmieren, so dermassen ignorant sein, dass sie nicht einmal die Grundsaeule des Typsystems verinnerlicht haben?

    Ich habe lange genug in der Uni / in einem Forschungsinstitut gearbeitet, wo sehr viele Stundenten hauptsächlich an Ergebnissen interessiert waren und erst während der Diplom/Master/PhD-Arbeit überhaupt mit C++ (teils als 1. Programmiersprache überhaupt) in Berührung gekommen sind. (Fast) niemand davon hat sich jemals für das Typsystem interessiert... Du kannst jetzt sagen, dass diese Leute alle C++ zwar für die Arbeit, aber nicht professionell einsetzen. Schön. Geht aber völlig an meiner Realität vorbei - Noob-Kompatibilität ist wichtig.


  • Mod

    Um die Diskussion mit dem kategorischen Imperativ abzuschliessen: Wer hier, ohne einen Rahmen zu setzen, postuliert, dass es sinnvoll sei, const vor Parameter zu setzen, um auch das schlimmste Greenhorn nicht zu verwirren, der suggeriert folglich, dass dies aus dem selben Grund in allen Bibliotheken und Projekten ueberall so getan werden sollte, was faktisch nirgends der Fall ist, und ausserdem krass schwachsinnig waere. Weil C++ nicht anfaengerfreundlich ist, niemals sein wird, und die Gemeinde sich aus praktischen Gruenden dagegen entschlossen hat, darauf Ruecksicht zu nehmen. Und weil jemand, der const vor Parametern braucht, um nicht verwirrt zu werden, keine genuegende Basis hat, um irgendein groesseres C++ Projekt selbststaendig einsetzen zu koennen.

    Ich bin mittlerweile schon skeptisch ob die Praemisse, dass es Leute gibt die int als Referenz missverstehen koennten, ueberhaupt zulaessig ist. Klingt unwahrscheinlich.



  • @wob sagte in Standardkonstrukor:

    Noob-Kompatibilität ist wichtig

    Und diese Noobs kennen die absoluten Basics der Sprache nicht, aber analysieren genau die Signatur jeder Funktion die sie verwenden? Das geht aber auch an der Realität vorbei.



  • @Jockelx Nein, das tun sie nicht. Aber du bringst denen bei "benutzt möglichst const" bei.

    Dass das hier überhaupt geht, ist sehr überraschend:

    struct X {
      X(const int some_stupid_name_or_no_name_at_all);
      int i;
    };
    
    X::X(int other_name) : i(other_name) {}
    
    int main() { X x(42); return x.i; }
    


  • @Columbo sagte in Standardkonstrukor:

    Edit: Das ist ein schlechtes Beispiel, weil Java fundamentale Typen nicht by-reference behandelt. Ich kann mir auf die schnelle tatsaechlich keine Beispielsprache ueberlegen, wo int standardmaessig eine Referenz ist.. was wiederum die Validitaet deines Arguments unterminiert...

    Ich mache u.a. HPC und da wird noch immer Fortran recht häufig verwendet, und etliche Personen kennen nur Fortran als Programmiersprache. Nimm einfach den folgenden Code speichere in als parameter.f90 ab, und übersetze ihn mit einem Fortran Compiler.

    program parameter
        use iso_fortran_env
        implicit none
    
        integer :: i = 1
    
        call foo(i)
        write(output_unit,*) i
    contains
        subroutine foo(i)
            integer :: i
    
            i = i + 1
        end subroutine foo
    end program
    

    Wer sich nicht die Mühe machen will, die Ausgabe ist natürlich 2 und nicht 1 wie Columbo das erwarten würde, da Fortran Parameter als Referenz übergibt.

    Programmieren ist kein obfuscated c contest.

    @Jockelx sagte in Standardkonstrukor:

    Mehr Glashäuser und Steine hab ich wohl noch nie gesehen....

    Du verwechselt hier eindeutig Ursache und Wirkung.



  • Eine dumme Frage. Was hält ihr von const Rückgabewerten?

    Ab und zu sehe ich nämlich Stilblüten in der folgenden Form.

    const bool Foo(const int a, const bool& b = true)
    


  • Der Gedanke hinter dem Code scheint dabei folgendermaßen zu sein: "Const Correctness = Ich mach mal überall const dran bis der Compiler meckert"



  • @Quiche-Lorraine

    Hier (mit bool) sehe ich zwar keinen Nutzen, aber wenn der Rückgabewert kein bool ist, sondern eine Klasse, dann macht das const schon Sinn.


  • Mod

    @Quiche-Lorraine sagte in Standardkonstrukor:

    Eine dumme Frage. Was hält ihr von const Rückgabewerten?

    Ab und zu sehe ich nämlich Stilblüten in der folgenden Form.

    const bool Foo(const int a, const bool& b = true)
    

    Gefährliches, veraltetes Halbwissen. Die Absicht war, vor langer, langer Zeit einmal, dass man Vollnoobs, die sowieso nichts damit anfangen könnten, vor an den Haaren herbei gezogenen Fehlern zu schützen. A la

    const MyClass foo();
    
    foo() = MyClass();  // Würde dadurch verhindert
    

    Würde niemand mit mehr als 5 Minuten Erfahrung jemals auch nur auf die Idee kommen, muss man also eigentlich gar keine Rücksicht drauf nehmen.

    Die Sache ist aber gefährlich geworden mit Move-Semantik, wo es jetzt richtige, sinnvolle Optimierungen in normalem Code verhindert, für den oben genannten nicht-vorhandenen Mehrwert.
    Siehe auch: https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#Rf-out

    Wenn man das also sieht, weiß man, dass man es mit jemandem zu tun hat, der seit 15 Jahren (C++11 ist viel älter als 2011…) nichts gelernt hat; und auch vorher schon war der const-Rückgabewert von fragwürdigem Nutzen.



  • @SeppJ sagte in Standardkonstrukor:

    vor an den Haaren herbei gezogenen Fehlern zu schützen

    Wobei dein Beispiel ja jetzt extra schlecht gewählt ist. Besser:

    struct A
    {
    ...
            A() = default;
            A(int pi)
    };
    A foo() {...}
    ...
    foo() = 42 // Tippfehler, wollte == schreiben. Kompiler ist aber glücklich
    

    Wollte jetzt hier aber auch keine Werbung für das const machen.
    Ich blätter von Zeit zu Zeit immer mal im alten Meyers und war das const noch als Tipp beim +-operator, daher bin ich da überhaupt erst drauf gekommen.


  • Mod

    @Jockelx sagte in Standardkonstrukor:

    @SeppJ sagte in Standardkonstrukor:

    vor an den Haaren herbei gezogenen Fehlern zu schützen

    Wobei dein Beispiel ja jetzt extra schlecht gewählt ist. Besser:

    struct A
    {
    ...
        int operator()(const A& a);
    };
    A foo() {...}
    ...
    foo() = 42 // Tippfehler, wollte == schreiben. Kompiler ist aber glücklich
    

    Es gibt gleich mehrere Gruende aus denen das nicht kompiliert, nicht zuletzt weil ein Zuweisungsoperator immer als Member aufgerufen wird.

    For the operators =, [], or ->, the set of non-member candidates is empty;

    Vielleicht wolltest Du eher einen converting ctor von int deklarieren?

    Das man prvalues von Klassentyp ueberhaupt etwas zuweisen kann, ist nur fuer ausgekluegelte Proxies gedacht. Fuer gewoehnliche Klassen sollte der operator= wahrscheinlich per ref-qualifier beschraenkt werden (was aber in der Praxis natuerlich niemand macht).


  • Mod

    @john-0
    Tatsaechlich habe ich mich gerade mit einem Arbeitskollegen unterhalten, der mir erklaert hat, dass in Fortran die Etiquette besteht, dass man nie einen Parameter aendern sollte, gerade weil dies zu boesen Fehlern fuehrt, wenn man Konstanten etc. als Argumente hat (und ganz frueher, aber das war in den 90ern schon folklore, konnte man auf bestimmten Maschinen sogar die integer literals aendern, weil sie im Datensegment gespeichert waren).
    Ein Fortran Fanatiker wuerde also das const sehen und sich nichts dabei denken, weil er sowieso annehmen wuerde, dass in einer Sprache, in der alles by reference ist, dieselbe Konvention aus den selben Gruenden gilt. 💡



  • @Columbo sagte in Standardkonstrukor:

    Vielleicht wolltest Du eher einen converting ctor von int deklarieren?

    Äh, keine Ahnung, wo ich da gerade war...aber ja, danke, das wollte ich. Habe es oben korrigiert.

    Edit:
    Naja, ich sehe gerade, dass ich da doch etwas rum basteln muss, um ein nicht zu-sehr-konstruiertes Beispiel zu kriegen.
    Da ich aber wie gesagt, ebenfalls das const da nicht haben will, habe ich auch keine Lust mehr was zu basteln.



  • Ich habe jetzt aber doch nochmal im Meyers (effective c++, item 3) nachgeschaut:
    Da sagt er, man solle den *-Operator einer 'Rational'-Klasse so deklarieren:

    const Rational operator*(const Rational& lhs, const Rational& rhs);
    

    Ist das einer der wenigen Tipps die Mist sind in dem Buch oder übersehe ich irgendwas, weil es ein operator ist und keine allgemeine Funktion?
    (und klar, das Buch ist pre-c++11, was den Tipp vielleicht damals noch legitimer machte).


  • Mod

    @Jockelx Der Grund ist doch schon genannt worden: Man soll nicht versehentlich r * s = t schreiben koennen. Allerdings waere Meyers sicherlich einverstanden, statt dem Rueckgabetyp jedes Operators const beizufuegen, einfach dem Zuweisungsoperator einen ref-qualifier zu verpassen:

    Rational& operator=(const Rational&) &;
    Rational& operator=(long) &;
    // ...
    

    Es ist tatsaechlich etwas enttäuschend, dass ein altes Proposal, welches jedem stdlib Zuweisungsoperator einen ref-qualifier verpassen sollte, vom LWG abgelehnt wurde.



  • @Columbo sagte in Standardkonstrukor:

    Der Grund ist doch schon genannt worden

    Ja, unter anderem von mir. Allerdings gab es die Behauptung von immerhin @SeppJ

    @SeppJ sagte in Standardkonstrukor:

    Gefährliches, veraltetes Halbwissen. Die Absicht war, vor langer, langer Zeit einmal, dass man Vollnoobs, die sowieso nichts damit anfangen könnten, vor an den Haaren herbei gezogenen Fehlern zu schützen.
    Würde niemand mit mehr als 5 Minuten Erfahrung jemals auch nur auf die Idee kommen, muss man also eigentlich gar keine Rücksicht drauf nehmen.

    Und da idR weder Meyers noch @SeppJ unsinn erzählen, wollte ich wissen, ob es sich bei operatoren anders verhält. Aber die Antwort hast du ja schon mit deinem Proposal gegeben, dass es zumnindest von mehreren im operator-Fall als problematisch angesehen wird.


  • Mod

    Ich bin nicht mit @SeppJ einverstanden, dass der Fehlermodus 'an den Haaren herbei gezogen' ist, was die Autoren des von mir angeführten proposals ähnlich gesehen haben (genau wie Meyers).

    Allerdings muss man eben auch einraeumen, dass der Fehlermodus in der Praxis selten auftreten kann, weil a) Compilerwarnungen, und b) es weitere Annahmen erfordert. Bspw. kann

    if (foo() = MyClass()) 
    

    überhaupt nur wohlgeformt sein wenn MyClass nach bool konvertierbar ist. Deshalb hat Meyers mit Rational ein treffliches Beispiel konstruiert, da Rational womöglich implizit nach double konvertierbar sein könnte. Per se sind das die meisten Klassen aber nicht.


Anmelden zum Antworten