Zuweisungsoperator Überladung



  • Code 1

    #include <iostream>
    using namespace std;
    
    struct Konto
    {
    	int guthaben;
    	void operator=(const Konto& Obj){
    		guthaben = Obj.guthaben;
    	}
    };
    
    int main()
    {
    	Konto Kol;
    	Kol.guthaben = 21850;
    	Konto Kol2;
    	Kol2 = Kol;
    	cout << Kol.guthaben << endl;
    
    	system("PAUSE");
    	return 0;
    }
    

    Code 2

    #include <iostream>
    using namespace std;
    
    struct Konto
    {
    	int guthaben;
    	Konto& operator= (const Konto& Obj){
    		guthaben = Obj.guthaben;
    		return *this;
    	}
    };
    
    int main()
    {
    	Konto Synic;
    	Synic.guthaben = 218449;
    	Konto SSYNIC;
    	SSYNIC = Synic;
    
    	system("PAUSE");
    	return 0;
    }
    

    Welchen Code sollte ich verwenden um den Zuweisungsoperator zu überladen?



  • Gar keinen, der Zuweisungsoperator wird automatisch definiert.

    Falls du unbedingt einen selber implementieren willst, dann nimm den zweiten und beachte die Regel der grossen drei.



  • Doch wenn ich Dynmaische Elemente in der Klasse habe muss ich einen eigenen Zuweisungsoperator definieren sonst würden beide Objekte auf die gleiche Adresse Zeigen (des dynmaischen elements) 😕



  • Der zweite ist viel viel viel üblicher als der erste.

    Damit es bei Konten klappt wie bei den ints und man folgenden Obersinnloscode schreiben kann:

    {
    	Konto Kol;
    	Kol.guthaben = 21850;
    	Konto Kol2;
    	cout << (Kol2=Kol).guthaben << endl;
    
    	system("PAUSE");
    	return 0;
    }
    

    Entsprechend wirste von allen hören, die erste Version sei schlicht falsch. Aber ich denke da anders. Zuweisungen dürfen gerne void zurückgeben, denn man mag Zuweisungen nie im selben Ausdruck noch weiterverwenden.

    Es könnte sein, daß manche Containerklassen dann keine Konten mehr verwalten können. Nämlich wenn deren Programmierer besoffen waren und mit Obersinnloscode protzen. Das dürfen sie sogar, da hats der Standard wiedermal versaubeutelt, http://en.cppreference.com/w/cpp/concept/CopyAssignable

    ~(Mal schauen, wie laut der Shitstorm wird.)~



  • Aufs reale Leben bezogen, würde ich für eine Konto-Klasse den Zuweisungsoperator wohl verbieten (sonst könnte man ja einfach das Guthaben ver-x-fachen ;-)...



  • Achso 😕 ok danke



  • volkard schrieb:

    Aber ich denke da anders. Zuweisungen dürfen gerne void zurückgeben, denn man mag Zuweisungen nie im selben Ausdruck noch weiterverwenden.

    Denkst du wirklich, dass
    - Standardkonformität vergeben (Container)
    - Keine Mehrfachzuweisungen (a=b=c) erlauben
    - Auf Konsistenz mit Builtin-Types und der restlichen C++-Community verzichten
    es wert ist, ein klein bisschen Schreibarbeit (return *this + type& statt void) zu sparen?

    Falls ja, stehst ziemlich alleine da.



  • shitstorm schrieb:

    volkard schrieb:

    Aber ich denke da anders. Zuweisungen dürfen gerne void zurückgeben, denn man mag Zuweisungen nie im selben Ausdruck noch weiterverwenden.

    Denkst du wirklich, dass
    - Standardkonformität vergeben (Container)
    - Keine Mehrfachzuweisungen (a=b=c) erlauben
    - Auf Konsistenz mit Builtin-Types und der restlichen C++-Community verzichten
    es wert ist, ein klein bisschen Schreibarbeit (return *this + type& statt void) zu sparen?

    Falsche Sichtweise das:
    - Man muss nicht jeden Mist mitspielen.
    - Zuweisungsauswertung (if(a=b)) verbieten. Und wer meint, a=b=c zu brauchen, gehört gefeuert.
    - Vorreiter sind halt nicht umfassend konsistent mit der Community. Konsistenz mit int, wozu denn? Doch nur für deine albernen Mehrfachzuweisungen. Um die Schreibarbeit gehts mir sicher nicht.

    shitstorm schrieb:

    Falls ja, stehst ziemlich alleine da.

    Nein, hast mich komplett falsch eingeschätzt. Und ja, ich weiß, daß ich ziemlich alleine dastehe. Das macht aber nix, ich weiß, daß sich void als Rückgabetyp von op= und op++ sehr gut macht.



  • volkard schrieb:

    - Zuweisungsauswertung (if(a=b)) verbieten.

    Mein Compiler warnt mich davor. Wenn ich es doch will, schreib ich if((a=b)) und bin froh, dass es geht.

    volkard schrieb:

    Um die Schreibarbeit gehts mir sicher nicht.

    Worum denn dann? Der einzige haltbare Grund scheint zu sein Mehrfachzuweisungen zu verbieten und (Kol2=Kol).guthaben. Missbrauch verhindern in dem man künstliche Limitationen einführt, wie Java.

    volkard schrieb:

    ich weiß, daß sich void als Rückgabetyp von op= und op++ sehr gut macht.

    Ich gebe zu, dass ich desöfteren op++ dereferenziere und ich finde den Code danach lesbarer.



  • shitstorm schrieb:

    volkard schrieb:

    - Zuweisungsauswertung (if(a=b)) verbieten.

    Mein Compiler warnt mich davor. Wenn ich es doch will, schreib ich if((a=b)) und bin froh, dass es geht.

    Zeig mir sinnvolle Mehrfachzuweisungen.



  • Nicht dass die Funktion an sich Sinn macht, aber hier gleich op++ und op= gemischt:

    template <typename IterIn, typename IterOut1, typename IterOut2>
    std::pair<IterOut1, IterOut2>
    simultaneous_copy(IterIn first, IterIn last, IterOut1 dest1, IterOut2 dest2) {
      while	(first != last)
        *dest1++ = *dest2++ = *first++;
      return {dest1, dest2};
    }
    


  • Die Funktion ist gar nicht so nutzlos. Zum Beispiel könnte man man: tee so nachprogrammieren:

    int main(int argc, const char *argv[])
    {
      if (argc != 2) return -1;
      if (std::ofstream out{argv[1]})
        simultaneous_copy(std::istreambuf_iterator<char>(std::cin),
                          {},
                          std::ostreambuf_iterator<char>(out),
                          std::ostreambuf_iterator<char>(std::cout));
      else
        return -2;
    }
    


  • shitstorm schrieb:

    Nicht dass die Funktion an sich Sinn macht, aber hier gleich op++ und op= gemischt:

    template <typename IterIn, typename IterOut1, typename IterOut2>
    std::pair<IterOut1, IterOut2>
    simultaneous_copy(IterIn first, IterIn last, IterOut1 dest1, IterOut2 dest2) {
      while	(first != last)
        *dest1++ = *dest2++ = *first++;
      return {dest1, dest2};
    }
    

    Und das Erhöhen ging echt nicht ein Zeilchen später?
    Ich bezweifle, daß deine Version lesbarer ist. Allenfalls dadurch, daß man sich so freut, so komplizierte Zeilen basteln zu können und sie deshalb sehr mag.

    K&R-strcpy:

    while(*dst++=*src++);
    

    Hier hat's tatsächlich eine gewisse Eleganz, daß man den Nullterminator nicht nach der Schleife noch dranbasteln muss.



  • Übrigens würde ich Minuszahlen als main-return vermeiden, 0,1,2 statt 0,-1,-2 gehn auch. Und gehn dann sogar auf anderen Betriebssystemen.



  • volkard schrieb:

    Übrigens würde ich Minuszahlen als main-return vermeiden, 0,1,2 statt 0,-1,-2 gehn auch. Und gehn dann sogar auf anderen Betriebssystemen.

    Aus welchem Grund meidest du dort Minuszahlen?



  • Also ich empfehle ja

    return 0x0;
    

    😃

    *duck'n'run*



  • out schrieb:

    volkard schrieb:

    Übrigens würde ich Minuszahlen als main-return vermeiden, 0,1,2 statt 0,-1,-2 gehn auch. Und gehn dann sogar auf anderen Betriebssystemen.

    Aus welchem Grund meidest du dort Minuszahlen?

    Weil DOS sie mißinterpretierte, -1 war 255 und so. Weil ich lieber 0 1 2 3 in die Doku schreibe, Minuszahlen nerven doch nur den Benutzer. Und weil ich einfach nicht irgendwann Plattformabhängig returnen will, wenn irgendwo die int-size sich ändert.



  • volkard schrieb:

    Und weil ich einfach nicht irgendwann Plattformabhängig returnen will, wenn irgendwo die int-size sich ändert.

    Der Standard spricht nur von 0 und non-null. Was das Betriebssystem mit dem genauen Int-Wert macht, ist sowieso platformabhängig (<-- kein Nomen).


Anmelden zum Antworten