Operatorüberladung



  • Hi, ich bin gerade dabei eine Klasse für rationale Zahlen zu schreiben, dabei sollen die 4 Grundrechenarten implementiert werden. Das wollte ich mit überladenen Operatoren machen. Bei operator+ mache ich allerdings was verkehrt. der Compiler schreibt mir:
    |59|error: 'Rn Rn::operator+(Rn, Rn)' must take either zero or one argument

    /*
    Entwerfen Sie einen ADT für rationale Zahlen. Implementieren Sie neben
    einem sinnvollen Konstruktor sowie Setter- und Getter-Methoden folgende
    Operationen:
    - Rückgabe des Dezimalwerts einer rationalen Zahl
    - weitestgehendes Kürzen der rationalen Zahl
    - Implementieren der vier Grundrechenarten
    Geben Sie dafür die Schnittstellen an und implementieren Sie den ADT!
    */
    
    #include <iostream>
    using namespace std;
    
    class Rn{
        private:
            int numerator;       //Zähler
            int denominator;     //Nenner
    
            int gcd(int a, int b){  //greatest common divisor
                if (a < 0) a *= -1;
                if (b < 0) b *= -1;
                if (a == 0 || b == 0) return 1;
                if (a < b) return gcd(a, b-a);
                if (a > b) return gcd(a-b, b);
                else return a;
            }
            void reduce_rationalNumber() {
                int factor = gcd(numerator, denominator);
                numerator /= factor;
                denominator /= factor;
            }
        public:
            Rn() {
                numerator = 0;
                denominator = 1;
            }
            int get_numerator() { return numerator; }
            int get_denominator() { return denominator; }
    
            void set_rationalNumber() {
                cout <<"\nNumerator: ";
                cin >> numerator;
    
                int d;          //Kontrollvariable damit Division durch 0 verhindert wird
                do {
                cout <<"Denominator: ";
                cin >> d;
                if ( d == 0 ) cout << "Not defined, enter again.\n";
                } while (d == 0);
                denominator = d;
                reduce_rationalNumber();
            }
            void get_rationalNumber() {
                cout <<"\n" << numerator << "/" << denominator;
            }
            void decimalValue() {
                cout << "\nDecimal: " << (numerator * 1.0) / (denominator * 1.0);
            }
            Rn operator+(const Rn a, const Rn b){   // a/b + c/d = (ad + bc) / bd
                Rn temp;
                temp.numerator = a.get_numerator() * b.get_denominator() + a.get_denominator * b.get_numerator();
                temp.denominator = a.get_denominator * b.get_denominator;
                return temp;
            }/*
            Rn operator-(Rn a, Rn b){
    
            }
            Rn operator*(Rn a, Rn b){
    
            }
            Rn operator/(Rn a, Rn b){
    
            }
    */
    
    };
    
    int main() {
        Rn a, b;
        Rn c;
        a.set_rationalNumber();
        a.get_rationalNumber();
        a.decimalValue();
    
        return 0;
    }
    


  • Wenn du die Operatoren als Klassen-Methode überlädst, dann mußt du nur einen Parameter entgegennehmen - als linker Operand wird *this verwendet.



  • Wenn du operator+ innerhalb der Klasse deklarierst, ist der erste Parameter durch this bereits implizit vorgegeben. Du kannst also die Parameterzahl auf 1 reduzieren oder (besser) den operator+ als freie Funktion definieren.

    BTW: Wenn du null Parameter hättest (was der Compiler dir zusätzlich vorschlägt), würdest du den unären operator+ überladen.



  • siehe zum Thema Operator-Überladung auch:
    Überladung von Operatoren in C++ (Teil 1)

    Teil 2 und Teil 3 sind in diesem Beitrag auch verlinkt.



  • Wo die eigentliche Frage jetzt beantwortet ist: Den Setter solltest Du auch nochmal überdenken. Erstens nimmt ein Setter normalerweise Parameter entgegen und liest nicht von cin. Zweitens ist so eine Rational-Klasse doch das Paradebeispiel für eine Wert- (und damit immutable-)Klasse, das heisst, eigentlich sollte es überhaupt keine Setter geben.



  • inter2k3 schrieb:

    siehe zum Thema Operator-Überladung auch:
    Überladung von Operatoren in C++ (Teil 1)

    Teil 2 und Teil 3 sind in diesem Beitrag auch verlinkt.

    Teil 2 und 3 zeigen eine komplette Rational-Klasse mit allen Operatoren, die man sich dafür nur wünschen kann. Voraussetzung ist boost.Operators



  • Vielen Dank für die Hilfe. Mein Programm sieht jetzt folgendermaßen aus:

    #include <iostream>
    using namespace std;
    
    class Rn{
        private:
            int numerator;       //Zähler
            int denominator;     //Nenner
    
            int gcd(int a, int b){  //greatest common divisor
                if (a < 0) a *= -1;
                if (b < 0) b *= -1;
                if (a == 0 || b == 0) return 1;
                if (a < b) return gcd(a, b-a);
                if (a > b) return gcd(a-b, b);
                else return a;
            }
            void reduce_rationalNumber() {
                int factor = gcd(numerator, denominator);
                numerator /= factor;
                denominator /= factor;
            }
        public:
            Rn() { numerator = 0; denominator = 1; }
            Rn(int n, int d) {
                this->numerator = n;
                this->denominator = d;
            }
            int get_numerator() const { return numerator; }
            int get_denominator() const { return denominator; } 
            void set_numerator(int n) { this->numerator = n; }
            void set_denominator(int d) { this->denominator = d; }
    
            void get_rationalNumber() const {
                cout <<"\n" << numerator << "/" << denominator;
            }
            void decimalValue() const {
                cout << "\nDecimal: " << (numerator * 1.0) / (denominator * 1.0);
            }
    };
    
    Rn operator+(Rn& a, Rn& b) {   // a/b + c/d = (ad + bc) / bd
        Rn temp;
        temp.set_numerator(a.get_numerator() * b.get_denominator() + a.get_denominator() * b.get_numerator());
        temp.set_denominator(a.get_denominator() * b.get_denominator());
        return temp;
    }
    Rn operator-(Rn& a, Rn& b) { // a/b - c/d = (ad - bc) / bd
        Rn temp;
        temp.set_numerator(a.get_numerator() * b.get_denominator() - a.get_denominator() * b.get_numerator());
        temp.set_denominator(a.get_denominator() * b.get_denominator());
        return temp;
    }
    Rn operator*(Rn& a, Rn& b) { // a/b * c/d = ac / bd
        Rn temp;
        temp.set_numerator(a.get_numerator() * b.get_numerator());
        temp.set_denominator(a.get_denominator() * b.get_denominator());
        return temp;
    }
    Rn operator/(Rn& a, Rn& b) { // a/b / c/d = ad / bc
        Rn temp;
        temp.set_numerator(a.get_numerator() * b.get_denominator());
        temp.set_denominator(a.get_denominator() * b.get_numerator());
        return temp;
    }
    
    int main() {
        Rn a(-1,2), b(1,2);
        Rn c = a+b;
        c.get_rationalNumber();
        c.decimalValue();
    
        return 0;
    }
    

    Bin mir nicht ganz sicher wo noch überall ein const fehlen könnte.



  • int gcd(int a, int b){  //greatest common divisor
                if (a < 0) a *= -1;
                if (b < 0) b *= -1;
    
    //            if (a == 0 || b == 0) return 1;//falsch, oder?
                if (a == 0 ) return b;
    //            if (b == 0 ) return a;//kommt eh nicht vor
    
                if (a < b) return gcd(a, b-a);
                if (a > b) return gcd(a-b, b);
                else return a;
            }
    

Log in to reply