3 Stimmen

Overladen des + Operators

Ich versuche, mich mit Operatoren in C++ vertraut zu machen. Ich dachte, ich würde das mit einem einfachen Fall der Vektoraddition tun. Leider scheine ich auf einige Probleme gestoßen zu sein. Meine Klassendefinition lautet wie folgt:

#ifndef _MVEC_H_
#define _MVEC_H_

#include "Error.h" //Ich definiere Dinge wie throw(message) hier, es funktioniert und ist nicht das Problem

class MVec {
        private:
                double vec[3];
        public:
                MVec();
                MVec(double &);
                MVec(double *);
                MVec(MVec &);
                MVec & operator=(MVec &);
                inline double & operator[](const int i);
                inline const double & operator[](const int i) const;
                MVec operator+(const MVec &) const;
                ~MVec();
};

MVec::MVec() {}

MVec::MVec(double &a) {
        for(int i = 0; i < 3; i++)
                vec[i] = a;
}

MVec::MVec(double *a) {
        for(int i = 0; i < 3; i++)
                vec[i] = *a++;
}

MVec::MVec(MVec &rhs) {
        for(int i = 0; i < 3; i++)
                vec[i] = rhs[i];
}

MVec & MVec::operator=(MVec &rhs) {
        if(this != &rhs)
                for(int i = 0; i < 3; i++)
                        vec[i] = rhs[i];

        return *this;
}

inline double & MVec::operator[](const int i) {
        #ifdef _CHECKBOUNDS_
        if(i < 0 || i >= 3)
                throw("Subscript out of bounds");
        #endif

        return vec[i];
}

inline const double & MVec::operator[](const int i) const {
        #ifdef _CHECKBOUNDS_
        if(i < 0 || i >= 3)
                throw("Subscript out of bounds");
        #endif

        return vec[i];
}

MVec MVec::operator+(const MVec &vec1) const {
        MVec ans;

        for(int i = 0; i < 3; i++)
                ans[i] = vec[i] + vec1[i];

        return ans;
}

MVec::~MVec() {
        delete[] vec;
}

#endif

Der [] Operator scheint wie beabsichtigt zu funktionieren. Leider funktioniert der Vektoradditionsoperator nicht. Speziell, wenn ich den Code ausführe:

#include "Error.h"
#include "MVec.h"
#include 
#include 

int main(int argc, char *argv[]) {
        MVec a, b, c;
        a[0] = 1; a[1] = 2; a[2] = 3;
        b[0] = 5.9906; b[1] = 72.1139; b[2] = 83.1324;

        //c = a + b;

        std::cout << (a + b)[0] << std::endl;
        std::cout << (a + b)[1] << std::endl;
        std::cout << (a + b)[2] << std::endl;

        exit(0);
}

Wenn ich die Zeile c = a + b; auskommentiere, erhalte ich einen Compilerfehler:

no match for 'operator=' in 'c = MVec::operator+(const MVec&) const(((const MVec&)((const MVec*)(& b))))'

Wenn ich es auskommentiere, erhalte ich nach dem ersten std::cout einen glibc detected Fehler. Vermutlich mache ich etwas falsch mit der temporären Variable, die ich in der operator+ Funktion erstelle. Leider bin ich nicht (ganz) schlau genug, um herauszufinden, was. Jeder Einblick dazu wäre sehr hilfreich.

8voto

juanchopanza Punkte 216358

Sie müssen einen const-Verweis auf MVec in Ihrem Kopierkonstruktor verwenden, um ihn mit temporären Objekten verwenden zu können:

MVec(const MVec &);

Dasselbe gilt für den Zuweisungsoperator und den Konstruktor, der einen double akzeptiert:

MVec(const double &); // oder kein Verweis, MVec(double);
MVec& operator=(const MVec& rhs);

Sie sollten auch das delete [] vec aus dem Destruktor entfernen, da vec nicht dynamisch allokiert ist. Dies ist wahrscheinlich die Ursache des glibc-Fehlers.

Jetzt, um Ausdrücke wie

SomeVec = 1.0 + SomeOtherVec;

zu ermöglichen, müssen Sie den operator+ als eine nicht parallele Funktion deklarieren:

MVec operator+(const MVec& lhs, const MVec& lhs); 

Dies ermöglicht implizite Konvertierungen sowohl auf der linken als auch auf der rechten Seite. Im Allgemeinen ist es eine gute Idee, solche Operatoren als nicht parallele Funktionen zu haben, um die Symmetrie zwischen linkem und rechtem Operanden zu garantieren.

Andererseits ergibt es wahrscheinlich mehr Sinn, die impliziten Konvertierungen von double überhaupt nicht zuzulassen. Dies können Sie erreichen, indem Sie den relevanten Konstruktor als explicit deklarieren:

explicit MVec(double);

2voto

Dietmar Kühl Punkte 145292

Der Kompilierzeitfehler ist leicht erklärt: Ihr Zuweisungsoperator erwartet ein nicht-const Referenzargument, aber Sie können keine nicht-const Referenz an eine temporäre Binden, da sie von Ihrem operator+() zurückgegeben wird. Die Art von naiver Lösung besteht darin, den Operator stattdessen ein const& nehmen zu lassen. Sie müssen jedoch tatsächlich gar keinen Kopierzuweisungsoperator definieren! Der vom Compiler generierte Kopierkonstruktor, die Kopierzuweisung und der Destruktor sind alle in Ordnung. Sie können sie einfach entfernen und es ist besser.

Insbesondere das Entfernen des Destruktors würde auch Ihr anderes Problem lösen: Sie rufen Speicher in Ihrem Destruktor mit delete[] auf, den Sie nicht allokiert haben! Dies sollten Sie niemals tun. Das heißt, wenn Sie Ihren Destruktor korrigiert haben, wäre er leer, d.h. Sie können ihn auch einfach entfernen.

1voto

evanmcdonnal Punkte 42430

Dies

MVec MVec::operator+(const MVec &vec1) const {
    MVec ans;

    for(int i = 0; i < 3; i++)
            ans[i] = vec[i] + vec1[i];

    return ans;
}

soll als eine Funktion außerhalb der Klasse definiert werden mit der MVec operator+(const MVec &vec1, const MVec &vec2) const Definition. Dann müssen Sie es ändern, um vec1[i] + vec2[i] hinzuzufügen, unter der Annahme, dass Ihr Ziel darin besteht, jeden Wert in den beiden Vektoren zu addieren.

Sie sollten auch Grenzprüfungen hinzufügen. Wenn die Länge eines der Vektoren kleiner als drei ist, wird es abstürzen. Sie sollten entweder bis zur Länge des kürzeren Vektors addieren oder gar nicht, wenn die Längen nicht gleich sind. Beispiel

 int loopVar = 0;
 if (vec1.length() > vec2.length())
     loopVar = vec2.length();
 else
     loopVar = vec1.length();

 for (int i = 0; i < loopVar; i++)
      ans[i] = vec1[i] + vec2[i];

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X