Operatorüberladung sowie Optimierung einer Klasse



  • Anhand Volkards C++-Kurs wollte ich mal eine Klasse schreiben, die Integer durch Shifts verschlüsselt. Allerdings stoße ich da aufgrund meines begrenzten Wissens noch auf Probleme.

    1. Wie überlade ich +=, -=, usw. Operatoren?
    2. Wie übergebe ich am Besten die Anzahl der Shifts, die generell durchgeführt werden sollen? Ich hatte da an eine static-Variable gedacht, die vom Konstruktor aufgerufen wird, aber wie muß es dann im Code aussehen (bisher ist es ja fix auf 1)?

    Vielen Dank im Voraus 🙂

    #include <iostream>
    
    class CTest
    {
    	int wert;
    	public:
    		int GetValue(void)
    		{
    			return RotR(wert, 1);
    		}
    
    		int RotL(unsigned int value, int n)
    		{
    			unsigned int temp = (value << n) | (value >> (32 - n));
    			return temp;
    		}
    
    		int RotR(unsigned int value, int n)
    		{
    			return RotL(value, 32 - n);
    		}
    
    		CTest() 
    		{ 
    			wert = RotL(0, 1); 
    		}
    
    		CTest(int value) 
    		{ 
    			wert = RotL(value, 1); 
    		}
    
    		CTest operator+(CTest value)
    		{
    			int erg = RotR(wert, 1) + RotR(value.wert, 1);
    			CTest temp(erg);
    			return temp;
    		}
    
    		CTest operator-(CTest value)
    		{
    			int erg = RotR(wert, 1) - RotR(value.wert, 1);
    			CTest temp(erg);
    			return temp;
    		}
    
    		CTest operator*(CTest value)
    		{
    			int erg = RotR(wert, 1) * RotR(value.wert, 1);
    			CTest temp(erg);
    			return temp;
    		}
    
    		CTest operator/(CTest value)
    		{
    			int erg = RotR(wert,1) / RotR(value.wert, 1);
    			CTest temp(erg);
    			return temp;
    		}
    
    		CTest operator%(CTest value)
    		{
    			int erg = RotR(wert, 1) % RotR(value.wert, 1);
    			CTest temp(erg);
    			return temp;
    		}	
    
    /*		CTest operator+=(int value)
    		{
    			int erg = RotR(wert, 1) + value;
    			CTest temp(erg);
    			return temp;
    		}*/
    };
    
    int main(void)
    {
    	CTest zahl1(10);	
    	CTest zahl2(20);
    	CTest zahl3 = zahl1 + zahl2;
    	zahl3 = zahl3 + 5;
    	int zahl = zahl3.GetValue();
    	std::cout << zahl << std::endl;
    	std::cin >> zahl;
    
    }
    


  • @1: Ich würde es eher umgekehrt machen und + durch += ausdrücken:

    CTest& CTest::operator +=(const CTest& other)
    {
      wert=RotL( RotR(wert,x)+RotR(other.wert,x) , x);
      return this;
    }
    
    CTest CTest::operator+(const CTest& other);
    {
      CTest tmp(*this);
      return tmp+=other;
    }
    

    @2: Nimm dir noch eine zweite Membervariable, deren Wert du im Konstruktor übergibst.



  • Nachtrag: Zu 2 ist mir noch eine bessere Lösung eingefallen - lagere alle Rechenoperationen in eine seperate Klasse CTest_Helper aus, die nur von CTest erzeugt werden kann (private Konstruktoren und friend) und stelle dann per CTest::operator() jeweils ein Objekt zur Verfügung, mit dem gerechnet werden kann.



  • @1: Das scheint so nicht zu funktionieren, jedenfalls frißt der Compiler es nicht
    "error C2143: Syntaxfehler : Fehlendes ';' vor '+='" und "error C2580: Neudefinition des Klassennamens 'CTest'" bringt er für Dein Überladevorschlag von +=

    @2: Dazu muß ich mir mal die Frienddefinition anschauen, das wird aber erst morgen/übermorgen was 😉



  • Du mußt die entsprechenden Opratoren auch innerhalb der Klasse deklarieren 😉 Sonst wundert sich der Compiler später, woher die kommen.



  • Ich hab's im public-Bereich der Klasse deklariert, oder was meinst Du? *nixpeil*



  • UNeverNo schrieb:

    Ich hab's im public-Bereich der Klasse deklariert, oder was meinst Du? *nixpeil*

    zeig doch am besten nochmal ein kleines stück code (von der deklaration in klasse und definition)



  • Das von CStoll gepostete Format ist für ausserhalb der Klasse gedacht (Definition, von Klassendeklaration getrennt). Dazu kommt ein einfacher Tippfehler: Das Semikolon am Ende des zweiten Funktionskopfes.

    Du solltest schleunigst lernen wie man in C++ die Definition von der Deklaration trennt, damit Du demnächst solche Beispiele lesen kannst und nicht über (einfachste) Tippfehler der Helfenden stolperst 😉



  • LordJaxom schrieb:

    Du solltest schleunigst lernen wie man in C++ die Definition von der Deklaration trennt, damit Du demnächst solche Beispiele lesen kannst und nicht über (einfachste) Tippfehler der Helfenden stolperst 😉

    hier im post hab ich den aber auch übersehen *schäm*



  • LordJaxom schrieb:

    Das von CStoll gepostete Format ist für ausserhalb der Klasse gedacht (Definition, von Klassendeklaration getrennt). Dazu kommt ein einfacher Tippfehler: Das Semikolon am Ende des zweiten Funktionskopfes.

    Du solltest schleunigst lernen wie man in C++ die Definition von der Deklaration trennt, damit Du demnächst solche Beispiele lesen kannst und nicht über (einfachste) Tippfehler der Helfenden stolperst 😉

    Ach, das mit dem Semikolon habe ich schon gesehen.

    Deklaration ist z.B.

    int foo(void);
    

    Definition dann

    int foo(void)
    {
      return 123;
    }
    

    Wüßte nicht wie mir das weiterhilft...



  • nein, ich meine von deinem operator der nicht funktioniert!



  • @UNeverNo:

    Wenn Du das weisst kannst Du mir bestimmt auch sagen wieso diese Information Dir nicht hilft, in folgendem Code einen Fehler zu finden.

    CTest CTest::operator+(const CTest& other);
    {
      CTest tmp(*this);
      return tmp+=other;
    }
    

    EDIT: Bzw, dass das nur einer von den zwei Compiler-Fehlern ist war mir übrigens schon klar. Der andere Compilerfehler kommt vermutlich weil Du den Code direkt in die Klasse eingesetzt hast (richtig?)



  • Wie gesagt das Semikolon ist zuviel, aber der Fehler kommt schon beim überladen von += und wie gesagt habe ich es in den public-Bereich der Klasse gepappt.

    Wüßte nicht wohin/wie sonst.

    Würde sonst nicht hier im Forum posten :D;)



  • Deshalb sagte ich Du sollst die Trennung lernen 😉

    class CTest {
      CTest operator+(const CTest& other)
      {
        CTest tmp(*this);
        return tmp+=other;
      }
    };
    

    Entweder so (ohne Trennung, ohne Semikolon, ohne CTest::) oder

    /* .h File */
    class CTest {
      CTest operator+(const CTest& other);
    };
    
    /* .cpp File */
    CTest CTest::operator+(const CTest& other)
    {
      CTest tmp(*this);
      return tmp+=other;
    }
    

    Wobei die Trennung nicht unbedingt in verschiedene Dateien stattfinden muss, aber das macht i.A. Sinn 😉



  • und ich würde deinen code von der klassendeklaration und der definition des operators trotzdem gern sehen!

    Sonst wird das ja ein rätselraten!



  • ser1al schrieb:

    und ich würde deinen code von der klassendeklaration und der definition des operators trotzdem gern sehen!

    Sonst wird das ja ein rätselraten!

    Ich kleiner, unwissender Anfänger hatte das Beispiel 1:1 übernommen, weil mir der Kopf

    CTest& CTest::operator+=(const CTest& other)
    

    nichts gesagt hatte mit dem doppelten CTest und dann noch die Referenz am Anfang. Praktisch sah es so aus:

    class CTest
    {
      int wert;
      public:
        //Konstruktor, RotR, RotL s. Eingangspost
        CTest& CTest::operator +=(const CTest& other)
        {
          wert=RotL( RotR(wert,x)+RotR(other.wert,x) , x);
          return this;
        } 
    }
    

    Das alles steht erstmal nur in meiner main.cpp, Headerdatei usw. mache ich erst, wenn der Test erfolgreich läuft 😉



  • UNeverNo schrieb:

    ser1al schrieb:

    und ich würde deinen code von der klassendeklaration und der definition des operators trotzdem gern sehen!

    Sonst wird das ja ein rätselraten!

    Ich kleiner, unwissender Anfänger hatte das Beispiel 1:1 übernommen, weil mir der Kopf

    CTest& CTest::operator+=(const CTest& other)
    

    nichts gesagt hatte mit dem doppelten CTest und dann noch die Referenz am Anfang.

    Das erste CTest& ist der Rückgabetyp des Operators (btw, im Nachhinein ist mir noch ein Fehler in der Funktion aufgefallen - das muß natürlich "return *this;" lauten), das zweite CTest:: kennzeichnet die Funktion als Element der Klasse CTest (und das ist unnötig, wenn du die Funktion innerhalb der Klassendeklaration aufzählst).



  • siehst du, es lag an der trennung, worauf dich LordJaxom weiter oben schon hingewiesen hatte 🙂

    in der classe kannst du das CTest:: weglassen!
    das brauchst du aber, wenn du die definition ausserhalb der klasse machst (also deklaration in .h, definition in .cpp)!


Anmelden zum Antworten