3

私はC++の演算子に慣れようとしています。ベクトル加算の単純なケースでそうするだろうと思いました。残念ながら、私はいくつかの問題に遭遇したようです。私のクラス定義は次のとおりです。

#ifndef _MVEC_H_
#define _MVEC_H_

#include "Error.h" //I define things like throw(message) here, it works and is not the issue

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

[]演算子は意図したとおりに機能しているようです。残念ながら、ベクトル加算演算子はそうではありません。具体的には、コードを実行すると次のようになります。

#include "Error.h"
#include "MVec.h"
#include <cstdlib>
#include <iostream>

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);
}

行のコメントを外すと、c = a + b; コンパイラエラーが発生します:

'c = MVec :: operator +(const MVec&)const(((const MVec&)((const MVec *)(&b))))'の'operator='に一致しません

コメントアウトすると、最初のstd::coutの後にglibcが検出したエラーが発生します。おそらく、operator+関数で作成している一時変数で何か問題が発生しています。残念ながら、私は(かなり)賢くなく、何を理解することができません。これに関するありとあらゆる洞察は非常に役立ちます。

4

3 に答える 3

8

一時的に使用できるようにするには、コピーコンストラクタでへのconst参照を取得する必要があります。MVec

MVec(const MVec &);

同じことが代入演算子にも当てはまり、コンストラクターは:を取りdoubleます

MVec(const double &); // or no reference, MVec(double);
MVec& operator=(const MVec& rhs);

は動的に割り当てられないdelete [] vecため、デストラクタからも削除する必要があります。vecこれがglibcエラーの原因である可能性があります。

さて、

SomeVec = 1.0 + SomeOtherVec;

operator+非メンバー機能としてを宣言する必要があります。

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

これにより、LHSとRHSの両方で暗黙的な変換が可能になります。一般に、LHSオペランドとRHSオペランドの対称性を保証するために、これらのタイプの演算子を非メンバー関数として使用することをお勧めします。

一方、暗黙の変換doubleをまったく許可しない方がおそらく理にかなっています。これは、関連するコンストラクターを作成することで実現できますexplicit

explicit MVec(double);
于 2012-11-19T19:55:20.670 に答える
2

コンパイル時のエラーは簡単に説明できます。代入演算子は非参照を引数として想定していますが、非参照を一時変数から返されるためconstバインドできません。単純な修正の種類は、代わりに演算子を使用することです。ただし、実際には、コピー代入演算子を定義する必要はまったくありません! コンパイラによって生成されたコピー構造、コピー代入、およびデストラクタはすべて問題ありません。それらを削除するだけで、より良い結果が得られます。constoperator+()const&

特に、デストラクタを削除すると、他の問題も解決delete[]されます。割り当てていないデストラクタでメモリを使用しています。これは絶対にしないでください。つまり、デストラクタを修正すると空になります。つまり、削除することもできます。

于 2012-11-19T20:00:02.120 に答える
1

これ

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

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

    return ans;
}

this 定義を使用して非メンバー関数として定義する必要があり MVec operator+(const MVec &vec1, const MVec &vec2) constます。次に、vec1[i] + vec2[i] を追加するように変更する必要があります。2 つのベクトルのすべての値を追加することが目標であると仮定します。

また、境界チェックを追加する必要があります。いずれかのベクトルの長さが 3 未満の場合、クラッシュします。短いベクトルの長さまで追加するか、すべての長さが同じでない場合は追加しないでください。例

 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];
于 2012-11-19T19:56:53.207 に答える