+ Operator für eigenen Datentyp



  • Hallo Leute!

    Ich habe einen langen ganzzahligen Integer als Klasse programmiert. Leider weiß ich nicht genau wie ich es mache, dass z.B. der "=" Operator funktioniert.

    class LONGINT {
    public:
    	bool bit[512];
    	LONGINT();
    	LONGINT(double zahl);
    	LONGINT LONGINT::operator=(LONGINT zahl);
    	double toDouble();
    
    };
    
    LONGINT LONGINT::operator=(LONGINT zahl) {
    	LONGINT kopie();
    	for(i=0;i<sizeof(LONGINT) {
    		kopie.bit[i]=zahl.bit[i];
    	}
    	return kopie;
    }
    

    Kann mir da jemand auf die Sprünge helfen?



  • class LONGINT { //warum caps? sieht aus wie makro aber nicht wie klasse...
    public:
        bool bit[512];
        LONGINT();
        LONGINT(double zahl);
        LONGINT& operator=(const LONGINT &zahl); //so geht das...
        double toDouble();
    };
    
    LONGINT& LONGINT::operator=(const LONGINT &zahl) {
        //das ist falsch: LONGINT kopie();
        for(i=0; i<sizeof(LONGINT) { //find ich auch nicht gerade elegant - vll solltest du eher nen static const size_t in deiner klasse für die länge speichern ^^
            bit[i]=zahl.bit[i]; //entspricht ja this->bit[i] = zahl.bit[i];
        }
        return *this; //der rückgabewert ist der gerade zugewiesene wert - also das gerade bearbeitete objekt (ein dereferenziertes this)
    }
    

    besser?
    bb



  • Hallo unskilled!

    Erstmal vielen Dank für deine Antwort.

    Leider will er trotzdem noch nicht.

    class LONGINT {
    public:
    	bool bit[512];
    	LONGINT();
    	LONGINT(double zahl);
    	LONGINT& operator=(const LONGINT &zahl);
    	double toDouble();
    
    };
    
    LONGINT& LONGINT::operator=(const LONGINT &zahl) {
    	int i;
    	for(i=0;i<sizeof(LONGINT);i++) {
    		bit[i]=zahl.bit[i];
    	}
    	return *this;
    }
    
    void main() {
    	LONGINT zahl1(1e100);
    	LONGINT zahl2();
    	zahl2=zahl1;  //error C2659: '=' : overloaded function as left operand
    	printf("%g\n\n", zahl2.toDouble());   //error C2228: left of '.toDouble' must have class/struct/union type
    }
    

    Es gibt keinen Fehler, wenn...

    void main() {
        LONGINT zahl1(1e100);
        LONGINT zahl2();
        //zahl2=zahl1;
        printf("%g\n\n", zahl1.toDouble());
    }
    


  • Oh ich bin ein Trottel.

    Es geht doch! LONGINT zahl2(); hat nicht funktioniert. Vielen Dank nochmal!



  • LONGINT zahl2();
    

    Das ist eine Funktionsdeklaration. 😉



  • Ja, und die Definition sieht so aus:

    LONGINT::LONGINT() {
    	int i;
    	for(i=0;i<sizeof(bit);i++) {
    		bit[i]=0;
    	}
    }
    

    Warum geht das nicht?



  • Das sieht wie die Implementierung eines Konstruktor aus. Was geht an dem nicht?



  • drakon schrieb:

    Das sieht wie die Implementierung eines Konstruktor aus. Was geht an dem nicht?

    Richtig.

    void main() {
    	LONGINT zahl();
    	printf("%g\n\n", zahl.toDouble()); //error C2228: left of '.toDouble' must have class/struct/union type
    }
    

    Wenn ich das printf rausnehme und den Debugger nach LONGINT zahl(); anhalte kennt er die Varianle zahl garnicht.

    ERROR: Symbol "zahl" not found



  • Er sprintg auch garnicht in den Konstruktor rein.



  • Wie schon gesagt, beschreibt das hier:

    LONGINT zahl();
    

    Eine Funktionsdeklaration.

    Wenn du ein Objekt instanzieren willst, dann ohne die Klammern:

    LONGINT zahl;
    

    Ausser du willst natürlich einen nicht-Defaultkonstruktor aufrufen, dann kannst du natürlich noch die Argumente in den Klammern angeben.

    LONGINT zahl ( 2.0 ); //z.B
    

    Dann wird aber auch nicht der Default-Konstruktor aufgerufen, sondern einer der überladenen. (Dementsprechend auf eine anderen Implementierung davon).



  • Okay es funktioniert ohne Klammern.

    Ich versteh nur nicht ganz warum es jetzt beim überladenen geht und beim Defaultkonstruktor nicht. Ist das immer so?

    Bei beiden werden den Bits[0....x] 1en oder 0en zugewiesen.



  • dahaack schrieb:

    Okay es funktioniert ohne Klammern.

    Ich versteh nur nicht ganz warum es jetzt beim überladenen geht und beim Defaultkonstruktor nicht. Ist das immer so?

    Bei beiden werden den Bits[0....x] 1en oder 0en zugewiesen.

    Jopp, ist es...
    Weil der COmpiler denkt, dass das eine eine Funktionsdeklaration ist...

    LONGINT zahl();
    // ^-- Rückgabe-Typ
    //       ^----Name
    //           ^---Parameterliste (in dem Fal dann void)
    

    Wenn du mal überlegst sieht eine Funktionsdeklaration ja wirklich genau so aus:

    int getMyIQ()
    {
     return std::numeric_limits<int>::max(); //^^
    }
    

    bb



  • Okay 😉

    Vielen Dank euch beiden!



  • Wie mach ich das denn jetzt mit einem + Operator? Da will ich den linken Summanden ja nicht überschreiben, sondern nur das Zwischenergebnis nach links reichen.



  • dahaack schrieb:

    Wie mach ich das denn jetzt mit einem + Operator? Da will ich den linken Summanden ja nicht überschreiben, sondern nur das Zwischenergebnis nach links reichen.

    LONGINT operator + ( const LONGINT & lhs , const LONGINT & rhs )
    {
     LONGINT temp ( lhs );
     return temp += rhs;
    }
    

    Oder natürlich auch gleich die einzelnen Werten nehmen, addieren und dann ein neues Objekt erzeugen.

    EDIT:
    Natürlich musst du dazu auch zuerst den += - Operator definieren. Der ist aber prinzipiell dem = - Operator sehr ähnlich.



  • Leider bekomm ichs noch nicht hin. Der += Operator funzt. Beim + werden 2 Fehlermeldungen ausgegeben:

    class LONGINT {
    public:
    	bool bit[48];
    	LONGINT();
    	LONGINT(double zahl);
    	LONGINT& operator=(const LONGINT &zahl);
    	LONGINT& operator+=(const LONGINT &zahl);
    	LONGINT& operator+(const LONGINT & lhs, const LONGINT & rhs ); //error C2804: binary 'operator +' has too many parameters
    	double toDouble();
    
    };
    
    void main() {
    	LONGINT zahl1=120;
    	LONGINT zahl2=-10;
    	LONGINT zahl3(10);
    	zahl3=zahl1+zahl2; //error C2676: binary '+' : 'class LONGINT' does not define this operator or a conversion to a type acceptable to the predefined operator
    	printf("%g\n\n", zahl3.toDouble());
    	printf("%i\n\n", (int)(1&1));
    }
    
    LONGINT operator + ( const LONGINT & lhs , const LONGINT & rhs )
    {
     LONGINT temp ( lhs );
     return temp += rhs;
    }
    


  • Der Operator + sollte auch keine Memberfunktion sein. Verändert ja an keinem der beiden Objekte etwas. Also nimm sie einfach raus.



  • Die Memberfunktion ist die

    LONGINT& operator+(const LONGINT & lhs, const LONGINT & rhs );
    

    ?

    Wenn ich die Zeile rausnehme sagt er bei

    zahl3=zahl1+zahl2;
    

    error C2676: binary '+' : 'class LONGINT' does not define this operator or a conversion to a type acceptable to the predefined operator

    Ich checks nicht.



  • class LONGINT {
       // ...
    
       friend LONGINT operator+( const LONGINT&, const LONGINT& );
    };
    
    LONGINT operator+( const LONGINT& lhs, const LONGINT& rhs )
    {
       // Implementation
    }
    

    oder alternativ (z.B. für Einzeiler)

    class LONGINT {
       // ...
    
       friend LONGINT operator+( const LONGINT& lhs, const LONGINT& rhs ) { /* Implementation */ }
    };
    

    Was wichtig ist, ist zu bemerken, dass in beiden Fällen der operator+ KEINE Memberfunktion ist (der aufruf foobar.operator+( foo1, foo2 ) ist ungültig, da es eine Memberfunktion operator+ nicht gibt).



  • Jo, es funktioniert, Danke!

    Aber was ist denn jetzt eine Memberfunktion? Bei wiki steht:

    Memberfunktionen (auch Elementfunktionen oder Methoden genannt) sind innerhalb einer Klasse deklarierte Funktionen. In einem konsequent objektorientiert geschriebenen Programm sollte jede Funktion außer der Funktion main() Memberfunktion einer Klasse sein.

    Dadurch bin ich ja jetzt auch nicht viel schlauer geworden.


Anmelden zum Antworten