Operator Überladung



  • da geht aber ziemlich viel nicht...

    Johnny++ schrieb:

    String operator+=( const String& str1 ) //#1
     {
        String tmp(*this);
        delete [] buffer;
        len=tmp.len+str.1.len; //#2
        buffer=new char[len]+1; //#3
        strcpy( buffer, tmp.buffer);
        strcat( buffer, str1.buffer);
        return buffer; //#4
    }
    

    op+= gibt ne referenz zurück -> return *this;
    #2 wird syntax-mäßig voll in die hose gehen
    #3 hat nexus bereits erläutert

    bb



  • Also 2 war ein Tipfehler von mir

    und Rückgabeobjekt ist doch von der Klasse String, oder?

    Hier nochmal die Klasse:

    class String {
    private:
    char *buffer;
    unsigned int len;
    
    public:
    String( const char* s= "") {
    len= strlen(s);
    buffer= new char [len+1];
    strcpy( buffer, s );
    }
    ~String() {delete [] buffer;}
    
    String operator+=( const String& str1 ) {
        String tmp(*this);
        delete [] buffer;
        len=tmp.len+str1.len;
        buffer=new char[len]+1;
        strcpy( buffer, tmp.buffer);
        strcat( buffer, str1.buffer);
        return buffer;
    }
    }
    


  • und Rückgabeobjekt ist doch von der Klasse String, oder?

    Nein. Der Rückgabetyp sollte String& sein. Du veränderst da ja dein aktuelles Objekt, also solltest du dann auch eine Referenz auf das aktuelle Objekt zurückgeben.

    String s = "hallo ";
    (s += "Johnny++ ") += "wie geht es dir?";
    std::cout << s; // gäbe nur "hallo Jonny++" aus.
    


  • von der Sache her geht das so in etwa:

    class String
    {
    public:
      String()
      : content_(0), length_(0)
      {}
    
      String(const char* content)
      : content_(0), length_(std::strlen(content))
      {
        content_ = new char[length_+1];
        std::copy(content, content+length_, content_);
      }
    
      String(const String& other)
      : content_(0), length(other.GetSize())
      {
        content_ = new char[length_+1];
        std::copy(other.content, other.content+length_, content_);
      }
    
      unsigned int GetSize() const
      {
        return length_;
      }
    
      String& operator+= (const String& other)
      {
        if(other.GetSize() != 0)
        {
          String tmp(*this);
          delete []content_;
          length_ += other.GetSize();
          content_ = new char[length_+1];
          std::copy(tmp.content, tmp.content+tmp.GetSize(), content_);
          std::copy(other.content, other.content+other.GetSize(), content_+tmp.GetSize()+1);
        }
        return *this;
      }
    
    private:
      char* content_;
      unsigned int length_;
    };
    

    Ist aber alles nicht zu empfehlen (Quellcode-Duplizierung, nicht Exception-sicher, ...).
    Falls du also nur eine zuverlässige string-Klasse suchst, dann würde ich dir std::string empfehlen...

    bb

    PS: das length+1 brauchst du eigtl nirgendwo - also zumindest das +1.
    du setzt eh nirgendwo ne '\0' als ende-kennzeichen - brauchst du ja auch nicht. ich habs aber mal so beibehalten - falls du das irgendwo nutzt, hast du bisher aber vergessen, ihm nen wert zuzuweisen...



  • Also das Beispiel ist aus dem Buch C++ von A bis Z. Und zwar das erste zum Thema Operator Überladung. Da steht auch da, das das nicht gut gelöst ist, und man lieber die std string klasse nehmen soll. Außerdem, das nur das geht:

    string1+="....";
    string1+="....";

    Aber wieso braucht es eine Referenz, damit ich das auch hintereinander schreiben kann?

    Und was ist mit meinen Fragen vom Anfang:

    wieso wird hier das this objekt in tmp gebuffert? Was für einen Vorteil hat das?
    Code:

    wieso wird hier der SPeicher am Anfang der Methode freigegeben, da ist ja eig noch gar keiner reserviert, oder?



  • Johnny++ schrieb:

    string1+="....";
    string1+="....";

    Wenn nur das gehen sollte, dann brauchst du auch gar keinen Rückgabetyp.
    Aber man lehnt sich bei den Operatoren immer an den Operatoren für die build-in-datentypen an, und da geht eben auch sowas:

    int a = 3;
    int b = 4;
    
    int c = a+= b+= 1;
    //b == 4+=1 == 5
    //a == 3+=b == 8
    //c == a == 8
    

    Wenn man dort eine Kopie zurückgeben würde, würde man andere Werte herausbekommen...

    wieso wird hier das this objekt in tmp gebuffert? Was für einen Vorteil hat das?

    es hat den vorteil, dass es so geht^^
    man hat ja nur 2 objekte und muss eins davon verändern - braucht dafür allerdings die daten von beiden objekten wieder.
    das man den speicher zuvor löchen muss, um mehr speicher zu reservieren, sollte klar sein.

    wieso wird hier der SPeicher am Anfang der Methode freigegeben, da ist ja eig noch gar keiner reserviert, oder?

    doch - da ist speicher reserviert, weil zuvor ein konstruktor aufgerufen wird - wenn das nur der standard konstruktor ist(wo wirklich kein new[] zu finden ist, ist das deshalb nicht weiter schlimm, weil delete[] 0; wohl definiert ist)

    bb



  • nochmal eine Frage zu dem return Wert. So für die Anwendung wie in dem Buch hätte man die Methode doch auch void machen können, oder? Weil eig wird ja das Objekt direkt verändert. Was bringt der dann überhaupt? Aber ist der Rückabetyp laut Definition nicht eig. ein String Objekt?

    Weil es geht ja:
    [cpp]String operator+=(...[/cpp]



  • Der Rückgabewert des += Operators ist eigentlich normalerweise eine Referenz auf das Objekt selber. Siehe auch hier:

    http://magazin.c-plusplus.net/artikel/�berladung von Operatoren in CPlusPlus (Teil 1)



  • Ja das wurde ja schon gesagt. Ich würde nur gerne mal wissen, wie das in dem Beispiel im Buch ist. Weil als Rückgabetyp wird ja eig ein Objekt vom Typ String festgelegt, aber nur eine Eigenschaft von diesem zurückgegeben.



  • das hab ich doch schon in meinem post geschrieben!?

    Wenn nur das gehen sollte, dann brauchst du auch gar keinen Rückgabetyp.
    Aber man lehnt sich bei den Operatoren immer an den Operatoren für die build-in-datentypen an

    soll heißen: der rückgabetyp ist in dem fall völlig irrelevant, weil das zurückgegebene Objekt nirgendwo verwendet wird...
    Aber jz lies doch endlich mal den Artikel und frag erst danach weiter immerzu das gleiche...



  • gut ich werde mir den artikel durchlesen. mich hat eben nur verwirrt, dass als Rückgabetyp String angegeben wird, aber da steht return buffer, was ja nur ein Element von String ist. Da weis ich nicht, ob das so geht.



  • Jonny++nochmal eine Frage schrieb:

    gut ich werde mir den artikel durchlesen. mich hat eben nur verwirrt, dass als Rückgabetyp String angegeben wird, aber da steht return buffer, was ja nur ein Element von String ist. Da weis ich nicht, ob das so geht.

    das geht, weil es einen (nicht als explicit deklarierten) ctor gibt, der ein const char* als einziges argument akzeptiert...
    ist das gleiche wie:

    class foo
    {
    public:
      foo(int unsued) {}
    };
    
    foo get_foo()
    {
      return 5;
    }
    

    weil man das manchmal nicht möchte, gibt es das schlüsselwort explicit - das ist aber wieder eine andere baustelle ;o)

    bb


Anmelden zum Antworten