*Verwirrt*



  • #include <iostream>
    using namespace std;
    
    class Str
    {
         private:
              char string[50];
    
         public:
              Str(const char*);
    };
    
    Str::Str(const char* p)
    {
         cout << "Copy-constructor" << endl;
         strcpy(string, p);
    }
    
    int main()
    {
         Str kette_a="hallo";
         Str kette_b=kette_a;
    
         system("pause > nul");
         return 0; 
    }
    

    folgendes versteh ich net ... und zwar wird beim erzeugen des objects kette_a der copy-constructor aufgerufen das is mir noch klar aber wie wird kette_b initialisiert oder was wird dort fürne fkt aufgerufen? 😕 ? ich bekomm davon nämliche keine ausgabe und einen anderen konstruktor kanns ja net geben wenn ich bereits einen manuell gemacht habe

    dankö euch schonmal 🙂


  • Mod

    Das was du in deinem Programm Copy-Konstruktor genannt hast, ist ein normaler Konstruktor. Beim Erzeugen der Kette B wird ein richtiger Copykonstruktor aufgerufen. Da du den in deinem Programm nicht definiert hast, legt der Compiler einen Standardcopykonstruktor für dich an.

    Ein Konstruktor ist ein Copykonstruktor wenn er ein Element seiner eigenen Klasse als Argument hat.



  • Dweb schrieb:

    ...[/code]

    dankö euch schonmal 🙂

    Bitte verwende nicht die "code" sondern die "cpp"-Tags für die Darstellung von C/C++ Code.

    Dweb schrieb:

    folgendes versteh ich net ... und zwar wird beim erzeugen des objects kette_a der copy-constructor aufgerufen

    Nein, das ist kein copy-constructor.

    Der Kopierkonstruktor hätte in diesem Fall je nach Schreibstil den Aufbau:
    "Str(Str const &)" bzw "Str(const Str &)"

    "Str::Str(const char* p)" Ist einfach ein Konstruktor mit einem Argument, der damit auch automatisch den Standardkonstruktor (da nicht separat definiert) überschreibt.

    Str kette_a = "hallo"; // Konstrukoraufruf  "Str(char const *)"
    Str kette_b = kette_a; // Kopierkonstruktor "Str(Str const &)"
    kette_b = kette_a;     // Zuweisung         "Str& operator=(Str const &)"
    

    Dweb schrieb:

    ...und einen anderen konstruktor kanns ja net geben wenn ich bereits einen manuell gemacht habe...

    Doch kann es.

    C++ generiert aus folgender Klasse:

    class Foo
    {
    };
    

    automatisch:

    class Foo
    {
      public:
        Foo();                       // Standardkonstruktor
        Foo(Foo const &);            // Kopierkonstruktor
        ~Foo();                      // Destruktor
        Foo& operator=(Foo const &); // Zuweisungsoperator
    };
    

    Du hast einen Konstruktor geschrieben, dadurch wird der automatische Standardkonstruktor nicht mehr erzeugt, wohl aber die anderen Methoden.

    Mach mal folgendes in deiner Klasse (ohne zusätzliche Implementierung!):

    class Str
    {
      // <== Deinen bisherigen Str-Code einfügen
      private:
        Str(Str const &);
        Str& operator=(Str const &);
    };
    

    Damit unterbindest du die Erzeugung des Kopierkonstruktors und Zuweisungsoperators. Und versuch dann mal erneut zu linken... Du wirst einen Fehler bekommen da du den Kopierkonstruktor verwendest, dieser aber nicht existiert.

    cu André



  • ok gut zu wissen danke dir 🙂



  • Sorry, aber das funktioniert hinten und vorne nicht.
    1)

    Str kette_a="hallo";
    

    Was ist das? Du machst hier eine Zuweisung eines C-Strings an ein Klassenobjekt, ohne jemals den =-Operator überladen zu haben. Kann nicht funktionieren. Der Compiler weiß doch überhaupt nicht, was er damit machen soll.
    2)

    system("pause > nul");
    

    System-Aufrufe sind per se weniger gut, da sie eben systembezogen sind.
    3)

    char string[50];
    

    Das würdest du wohl besser in den Konstruktor stecken und da dann dynamisch Speicher anfordern. Du sparst Speicherplatz.
    4)

    strcpy
    

    Die Funktion steckt erstens in <cstring> und ist zweitens gefährlich, weil sie keine Längenprüfung hat.
    5)

    und zwar wird beim erzeugen des objects kette_a der copy-constructor aufgerufen

    Es gibt keinen Copy-Konstruktor. Ein Kopierkonstruktor würde als Argument ein Objekt bzw. besser eine Objektreferenz vom gleichen Klassentyp annehmen. Also sowas wie "Str::Str(const Str&)". Es soll ja ein Objekt kopiert werden.
    6)

    wie wird kette_b initialisiert oder was wird dort fürne fkt aufgerufen?

    Wie unter 6. schon, wird hier keine Funktion aufgerufen. Es wird lediglich versucht, den =-Operator aufzulösen (ja, das wird letztlich wieder zur Funktion), was aber nicht gelingt.
    7)

    Str::Str(const char* p)

    Ja, das ist dein Konstruktor. Kein Kopierkonstruktor, einfach dein parametrisierter Konstruktor.

    Edit: Hui, da waren aber einige schneller.



  • asc schrieb:

    Damit unterbindest du die Erzeugung des Kopierkonstruktors und Zuweisungsoperators. Und versuch dann mal erneut zu linken... Du wirst einen Fehler bekommen da du den Kopierkonstruktor verwendest, dieser aber nicht existiert.

    Wird er nicht vielmehr eine Fehlermeldung bekommen dass er den privaten Konstruktor aufruft? Der Aufruf an sich ist doch schon illegal, bis zum Linker kommts doch garnicht oder irre ich mich?

    moagnus schrieb:

    Sorry, aber das funktioniert hinten und vorne nicht.
    1)

    Str kette_a="hallo";
    

    Was ist das? Du machst hier eine Zuweisung eines C-Strings an ein Klassenobjekt, ohne jemals den =-Operator überladen zu haben. Kann nicht funktionieren. Der Compiler weiß doch überhaupt nicht, was er damit machen soll.

    Doch weiß er. Da kette_a hier initialisiert wird, wird der C-String Konstruktor von Str aufgerufen, und der existiert. Genauer gesagt wird obiger Ausdruck wie folgt übersetzt:

    Str kette_a( Str("hallo") );
    

    Also generierung eines temmporären Objekts mit dem C-String Ctor gefolgt vom Aufruf des Copy-Ctors. Das temporäre Objekt wird meist wegoptimiert, allerdings muss der Copy-Ctor aufrufbar sein.

    Str kette_b=kette_a;
    

    Selbiges gilt hierfür. Vergleich das mal mit dem Code oben. Einmal steht rechts vom '=' ein C-String, beim zweiten Mal steht da ein Str-Objekt. Der Compiler kann nicht raten, wie er in den zwei unterschiedlichen Fällen damit umgehen kann.[/cpp]

    Diesmal wird direkt der Copy-Ctor aufgerufen.

    und zwar wird beim erzeugen des objects kette_a der copy-constructor aufgerufen

    Es gibt keinen Copy-Konstruktor. Ein Kopierkonstruktor würde als Argument ein Objekt bzw. besser eine Objektreferenz vom gleichen Klassentyp annehmen.

    Wie weiter oben gesagt wurde gibts den sehr wohl (implizit generiert nämlich), und er wird sogar aufgerufen, wenn auch anders als der OP vermutet hat - der Aufruf kann wie gesagt aber wegoptimiert werden.


  • Mod

    moagnus schrieb:

    Sorry, aber das funktioniert hinten und vorne nicht.
    1)

    Str kette_a="hallo";
    

    Was ist das? Du machst hier eine Zuweisung eines C-Strings an ein Klassenobjekt, ohne jemals den =-Operator überladen zu haben. Kann nicht funktionieren. Der Compiler weiß doch überhaupt nicht, was er damit machen soll.

    Das ist eine (Copy-)Initialisierung und keine Zuweisung. Mithin wird versucht, den initialisierenden Ausdruck in ein Str-Objekt zu konvertieren, was den Aufruf eines entsprechenden Konstruktors, den wir in diesem Fall haben, bewirkt.

    moagnus schrieb:

    Str kette_b=kette_a;
    

    Selbiges gilt hierfür. Vergleich das mal mit dem Code oben. Einmal steht rechts vom '=' ein C-String, beim zweiten Mal steht da ein Str-Objekt. Der Compiler kann nicht raten, wie er in den zwei unterschiedlichen Fällen damit umgehen kann.
    Eine Lösung wäre, den =-Operator für C-Strings und für Str-Objekte zu überladen, damit da eine richtige Zuweisung stattfinden kann.

    ditto, nur hat der initialisierende Ausdruck bereits den richtigen Typ, folglich wir nur einfach kopiert.

    Den Unterschied zwischen Initialisierung und Zuweisung solltest du dir noch einmal klar machen.



  • moagnus schrieb:

    Edit: Hui, da waren aber einige schneller.

    Nicht nur das... auch weitaus richtiger 😉

    In einen einzigen Punkt gebe ich dir aber Recht: <cstring> gehört nicht in ein C++ Programm für Anfänger (Es mag Ausnahmefälle geben wo die C-Bibliotheken Sinn machen können, aber dann bitte nur wenn ein Profiler dies auch nachweist...). Und std::string ist lesbarer und leichter anzuwenden.

    cu André



  • Den Unterschied zwischen Initialisierung und Zuweisung solltest du dir noch einmal klar machen.

    Da muss ich dir recht geben. Das war wohl der Hauptgrund für meine Fehler. Und an die automatische Generierung von Kopierkonstruktor und Zuweisungsoperator hab ich leider auch nicht mehr gedacht.

    Und std::string ist lesbarer und leichter anzuwenden

    Aber vllt. nicht ganz die richtige Wahl, wenn man eine eigene String-Klasse bauen will.



  • moagnus schrieb:

    Und std::string ist lesbarer und leichter anzuwenden

    Aber vllt. nicht ganz die richtige Wahl, wenn man eine eigene String-Klasse bauen will.

    Ja. Und diese Implementierung benutzt du dann Wahrscheinlich auch in grossen Projekten.. 🙄



  • Naja, um eine eigene String-Klasse zu schreiben (sei es nur als Übung), ist es schon eher erbärmlich, wenn man auf vorgefertigte Container wie std::string zurückgreifen muss 😉


Anmelden zum Antworten