Standardkonstruktor und Elementinitialisierung



  • Hi ihr,

    Ich habe mal ne kurze Verständnisfrage zu einigen syntaktischen Sachen.
    Und zwar, wenn ich eine Klasse ohne Standardkonstruktor habe, und ein Objekt dieser Klasser erstelle haben ja alle Werte undefinierte Bereiche, weil nur Speicherplatz zugewiesen wird.
    Beispielsweise so:

    Klasse K;
    

    Nun wird 'K' erzeugt.
    Wenn K beispielsweise ein öffentliches Integerelement 'hallo' hat, dann könnte man ja sagen:

    Klasse K;
    K.hallo = 4;
    cout << K.hallo << endl;
    

    Schreibe ich jedoch das Selbe folgendermaßen:

    Klasse K();
    K.hallo = 4;
    cout << K.hallo << endl;
    

    ... so passiert genau was?

    42 C:\Dokumente und Einstellungen\Praktikant\Eigene Dateien\Test\smallint.cpp request for member `hallo' in `K', which is of non-class type 'Klasse' ()()'
    

    Ich habe hinter K noch ein Klammerpaar gepackt.
    Es wird also kein Standardkonstruktor aufgerufen, sondern ein eigener, den es aber nicht gibt.
    Die Kompilierung schlägt aber nicht fehl.
    Erst dann, sobald ich ein Element von K ändere.
    Was genau ist der Unterschied zwischen Klasse K und Klasse K**()**???

    Darf ich die Klammern nie schreiben, wenn ich keinen eigenen Konstruktor definiert habe?

    Ich überleg schon seit längerem, was genau der Unterschied ist.

    Bis später

    David



  • Mit dem Befehl Klasse K; wird der Standardkonstruktor aufgerufen. Mit Klasse K(); deklarierst du eine Funktion K mit dem Rückgabetyp Klasse.
    Vergleiche mal int i; und int i();. i ist eine variable und i() eine Funktion.



  • Klasse k;
    int    i;
    //-----------------------
    Klasse k();
    int    i();
    

    Na, fällt dir was auf? 😉
    Übrigens, Klasse k; ruft den Default-Ctor auf.
    Bei C++ ist ein komplexer Typ nicht viel anders zu behandeln, als ein primitiver Typ. Du kannst ja auch sowas machen:

    Klasse *k = new Klasse;
    int    *i = new int;
    


  • Artchi schrieb:

    Klasse k;
    int    i;
    //-----------------------
    Klass k();
    int   i();
    

    Na, fällt dir was auf? 😉

    Ja, da fehlt ein e. :p 😃

    SCNR



  • Wie geil- das mit der Funktion ist mir garnicht aufgefallen 😃
    C++ ist schon so ne Sache...-.-^^



  • Mhh hab noch ne Frage.
    Wenn ihr schon dabei seid könntet ihr mir auch noch sagen, was bei dynamischen Objekten denn jetzt der Unterschied ist:

    #include <iostream>
    using namespace std;
    struct Markus
    {
       int a;
    };
    int main(void)
    {
       Markus * M = new Markus();
       M->a = 4;
    }
    

    Oder:

    #include <iostream>
    using namespace std;
    struct Markus
    {
       int a;
    };
    int main(void)
    {
       Markus * M = new Markus;
       M->a = 4;
    }
    

    Beides lässt sich problemlos kompilieren.

    cya

    David



  • Schreib doch einfach in den Default-Ctor ein Konsolen-Ausgabe rein, und beobachte was passiert. Man muß ja nicht jedes Detail, was man selber prüfen kann, hier fragen.

    struct Markus
    {
      Markus()
      {
         cout << "Ctor" << endl;
      }
      int a;
    };
    


  • Bei beidem geschieht das selbe.
    Aber weils ja C++ ist bin ich mir immer noch nicht sicher, ob beides wirklich das selbe ist.
    Also hab ich gefragt^^



  • Ubrigens heisst die main-funktion in C++ (und mittlerweile auch in C) immer

    int main()
    
    // oder:
    int main(int argc, char** argv);
    

    Denn

    void main(void)
    

    schrieb man nur frueher in C, und selbst dort ist es mittlerweile eigentlich nicht mehr erlaubt (die Compiler akzeptieren es in der Regel trotzdem noch).



  • Hallo,

    Bei dynamischer Erzeugung wie hier

    Markus * M = new Markus();
    

    kann der Compiler klar erkennen, dass hier ein Zeiger auf Markus erzeugt werden soll, egal ob Klammern oder nicht. Also interpretiert der Compiler das auch so.
    Bei diesem hier

    Markus M();
    

    geht das nicht mehr. Hier sind zwei Varianten möglich
    - Deklaration einer parameterlosen Funktion mit Rückgabetyp Markus
    - Deklaration einer Variablen vom Typ Markus mit Aufruf des Standardkonstruktors
    Die erste Variante hat mehr Priorität und wird deshalb auch gewählt.



  • Blue-Tiger schrieb:

    void main(void)
    

    schrieb man nur frueher in C, und selbst dort ist es mittlerweile eigentlich nicht mehr erlaubt (die Compiler akzeptieren es in der Regel trotzdem noch).

    Nein, früher schrieb man einfach

    main()
    

    , was int main() bedeutet. void main() war nie wirklich erlaubt, war aber praktischer und wurde deshalb wohl von Borland usw. propagiert, weil es den Compilern relativ schnurz war, wie main definiert ist, solange die Schnittstelle auf Assembler-Ebene irgendwie passt.



  • Bashar schrieb:

    Nein, früher schrieb man einfach

    main()
    

    , was int main() bedeutet. void main() war nie wirklich erlaubt, war aber praktischer und wurde deshalb wohl von Borland usw. propagiert, weil es den Compilern relativ schnurz war, wie main definiert ist, solange die Schnittstelle auf Assembler-Ebene irgendwie passt.

    Ich würde sogar soweit gehen zu behaupten, "void main()" wurde aus Unwissenheit darüber erschaffen, dass "main()" in C "int main()" entspricht und hat sich im Laufe der Zeit festgesetzt. Wobei ich das natürlich nicht belegen kann 😉


Anmelden zum Antworten