Muss man für Klassen bzw. Strukturen Operator= überladen ?



  • Hi, ich möchte eine Klasse bzw Struktur = einer anderen setzen...
    Muss ich einen operator= schreiben oder kann man einfach
    class = class bzw struct = struct ?? weil ich dachte immer
    strukuren bzw. klassen sind ja keine einfachen daten typen...

    Gruß Chris



  • Das hängt von der Art der Struktur ab. C++ definiert implizit immer einen Zuweisungsoperator, die Frage ist, ob er das macht, was du willst.

    P.S.: Warum meldest du dich nicht im Forum an?



  • Hab dieses Forum hier erst neulich gefunden 😉

    Danke, ne also wenn ich einen "operator=" explizit in die Klasse implementiere,
    dann wäre das ja z.b. folgender code:

    class Number
    {
       public:
          Number & operator=(const Number Obj);
    };
    
    Number & Number::operator=(const Number Obj)
    {
       m_Value = Obj.m_Value;
       return *this;
    }
    

    aber :

    Number & Number::operator=(const Number Obj) // <- hier wird doch als Parameter auch eine direkte Zuweisung gemacht.. 
    // ist das dann der "unsichtbar" mitkompilierte copy constructor ?
    


  • Das ist das Objekt, dass rechts vom = steht. Also findet da keine Zuweisung statt.



  • alles klar danke... echt jutes forum..


  • Mod

    mach ich 🙂 schrieb:

    Number & Number::operator=(const Number Obj) // <- hier wird doch als Parameter auch eine direkte Zuweisung gemacht..
    

    Ein Funktionsparameter wird beim Funktionsaufruf nicht zugewiesen sondern initialisiert. Die Initialisierung eines Klassenobjektes geschieht durch den Aufruf des entsprechenden Konstruktors. Falls der Typ des Arguments einen anderen Typ als Number hat, wird zunächst ein temporäres Objekt vom Typ Number erzeugt (entweder weil Number einen entsprechenden Konstruktor hat - hier nicht - oder weil das Argument ein Klassenobjekt mit einem entsprechenden Konvertierungsoperator ist) und der Funktionsparameter wird dann aus diesem Objekt (bzw., falls das Argument vom Typ Number war, aus dem Argument selber) durch Aufruf des hier implizit deklarierten Copy-ctors erzeugt. Falls eine Konvertierung stattgefunden hat, oder das Argument ein ungebundenes temporäres Objekt ist, darf der Compiler diese Kopie vermeiden.

    Wäre das Argument deines Operators kein Objekt sondern eine Referenz, wäre der Copy-ctor nat. aus dem Spiel, denn die Initialisierung einer Referenz geschieht ja nicht durch Aufruf eines Konstruktors (es könnte allerdings ein Konstruktor aufgerufen werden, um das Argument erst einmal passend zu konvertieren).



  • camper schrieb:

    Wäre das Argument deines Operators kein Objekt sondern eine Referenz, wäre der Copy-ctor nat. aus dem Spiel, denn die Initialisierung einer Referenz geschieht ja nicht durch Aufruf eines Konstruktors (es könnte allerdings ein Konstruktor aufgerufen werden, um das Argument erst einmal passend zu konvertieren).

    Um es leichter Verständlich zu machen:

    Grundsätzlich sollte man Call-By-Reference dem Call-By-Value vorziehen, außer es handelt sich um integrale Datentypen (int, bool, double...). Sonst verursachst du noch eine Kopie die nicht sein muss.

    Die Signatur des Zuweisungsoperators sollte daher so lauten:
    Number & Number::operator=(const Number**&** Obj);

    cu André



  • Number & Number::operator=(const Number& Obj);
    

    Obj wird erstellt (normaler constru.) und dann mit dem argument "ver-referenziert"
    Also ist Obj zu einer Art Zeiger geworden ... oder hab ich das jetzt falsch verstanden ? -> Ich hab diese Sachen noch nicht zu 100% drauf..

    Achja und warum muss eigentlich "operator+" einen rückgabewert haben ?
    -> den codeteil hatte ich aus einem tut das ich zur zeit durcharbeite...



  • nur zum verständnis... schrieb:

    Obj wird erstellt (normaler constru.) und dann mit dem argument "ver-referenziert"
    Also ist Obj zu einer Art Zeiger geworden ... oder hab ich das jetzt falsch verstanden ? -> Ich hab diese Sachen noch nicht zu 100% drauf..

    Eine Referenz ist ein Alias(-name). Im wesentlichen Bedeutet Referenz also das es sich tatsächlich um das Original handelt, nur unter einem neuen Namen / Sichtbereich. Im Prinzip gibt es gewisse Ähnlichkeiten zu Zeigern [unter der Haube können es auch durchaus Zeiger sein], nur unterscheiden sich Zeiger und Referenzen in einigen Punkten auch (nicht unbedingt vollständig):

    Referenzen verweisen auf genau eine Entsprechung. Du kannst werder eine Nullzuweisung machen noch den Verweis ändern (das Objekt wiederum ja, wenn es keine konstante Referenz ist). Referenzen erlauben eine schöner lesbare Syntax...

    nur zum verständnis... schrieb:

    Achja und warum muss eigentlich "operator+" einen rückgabewert haben ?

    Du möchtest sicherlich so etwas schreiben können:

    int a = 4 + 5;

    Orientiere dich immer an den Integralen Datentypen... Du musst einen Wert zurückgeben wenn du auch eine Zuweisung oder Weiterverarbeitung erlauben willst.

    Dabei gilt: Alle Operatoren die direkt auf das Objekt gehen (+=,-=...) sollten immer eine Selbstreferenz zurückgeben, Operatoren die das Objekt nicht direkt verändern (+,-...), sollten eine lokale Variable per Kopie zurückliefern...

    Nun kommen wir zu dem Operator wo einige sich immer fragen warum er in der einen Form performanter sein kann als in der anderen...:

    ++i vs i++

    int i = 0;
    std::cout << i;   // liefert 0
    std::cout << ++i; // liefert 1 (Direktes inkrement mit Referenzrückgabe)
    std::cout << i;   // liefert 1
    std::cout << i++; // liefert 1 (Indirektes Inkrement, alter Wert wird als Kopie zurückgegeben)
    std::cout << i;   // liefert 2
    

    Genauer: (Ich werde hier mal schlechten Stil wie public Member der Einfachheit machen...)

    stuct Zahl
    {
        long Value;
        const operator++();
        const operator++(int);
    };
    
    // Prefixversion: ++i
    const Zahl& Zahl::operator++()
    {
        ++this->Value;
        return *this;
    }
    
    // Postfixversion: i++ (der int Parameter dient nur der Unterscheidung)
    const Zahl Zahl::operator++(int)
    {
        Zahl temp(*this);  // Kopie merken (Kopierkonstruktoraufruf)
        ++this->Value;     // Inkrement
        return temp;       // Kopie zurückgeben (Wertrückgabe)
    }
    

    cu André



  • Ok referenzen hab ich nun verstanden aber eins begreif ich noch nicht...
    wenn man eine selbst referenz von sich gibt...
    zb.: Number & Number::operator=(const Number& Obj);

    wäre das ja sehr hilfreich bei folgendem aufruf:

    number a,b,c;
    
    a = b = c;
    

    aber b würde ja zu a eine referenz geben ... aber a ist ja keine referenz ...
    würde dann der copy constructor automatisch in kraft treten =?

    Gruß



  • Nein, a muss keine Referenz sein.

    Er ÜBERNIMMT lediglich in copy ctor (Konstruktor) eine Referenz und gibt eine Referenz von sich zurück, was hier aber (bei a) keine Rolle mehr spielt.


Anmelden zum Antworten