2016-04-30 5 views
1

オペレータオーバーロード関数の定義後にエラーが発生する理由はわかりません: 'operator ='(オペランドタイプは 'Matrix'と 'Matrix')、a1 + a4演算子+オーバーロード関数が返す1つの行列オブジェクトの後です。ここでa1 =オブジェクト行列ですか?C++オペレータオーバーロード

#include<iostream> 
using namespace std; 

//write your code here 
class Matrix{ 
    private: 
    int arr[3][3]; 
    public: 
    friend istream& operator >> (istream& in,Matrix &matrix); 
    friend ostream& operator << (ostream& out,const Matrix& matrix); 
    friend Matrix operator + (Matrix &a,Matrix &b); 
    void setArr(int i,int j,int data){ 
     arr[i][j] = data; 
    } 
    int getArr(int i,int j){ 
     return arr[i][j]; 
    } 
    Matrix& operator = (Matrix &b); 
}; 
istream& operator >> (istream& in,Matrix &matrix) 
{ 
    for(int i=0;i<3;i++) 
     for(int j=0;j<3;j++) 
      in >> matrix.arr[i][j]; 
    return in; 
} 
ostream& operator << (ostream& out,const Matrix &matrix){ 
    for(int i=0;i<3;i++) 
    { 
     for(int j=0;j<3;j++) 
      out << matrix.arr[i][j] << " "; 
     out << endl; 
    }  
    return out; 
} 
Matrix operator + (Matrix &a,Matrix &b){ 
    Matrix temp; 
    for(int i=0;i<3;i++) 
     for(int j=0;j<3;j++) 
      temp.setArr(i,j,(a.getArr(i,j)+b.getArr(i,j))); 
    return temp; 

} 
Matrix& Matrix::operator = (Matrix &b){ 
    for(int i=0;i<3;i++) 
     for(int j=0;j<3;j++) 
      arr[i][j] = b.getArr(i,j); 
    return *this; 
} 
int main() 
{ 
    Matrix a1,a2,a3,a4; 
    cin >> a1; 
    cin >> a2; 
    a4 = a2; 
    a3 = (a1+a4); //an error over there 
    cout << a1 << endl; 
    cout << a2 << endl; 
    cout << a3 << endl; 
    return 0; 
} 
+0

'Matrix&Matrix :: operator =(const Matrix&b){...}'を使用するとどうなりますか? **パラメータには 'const'を使用することに注意してください**。 –

+0

すでに述べられていること以外にも、演算子+()は引数として定数参照を取るべきでしょう。なぜなら、オペランドを変更することは想定されていないからです。現在の形では、あなたは 'a4 = a1 + a2 + a3'のようなことをすることもできません。 – Paulo1205

+0

これはかなり良いMatrixクラスです。私はすべての '3 'を' size'(constexpr size_t size = 3; ')で置き換えて、マジックナンバーを削除し、' int&operator()(int row、int column) 'をセルへのアクセスを提供し、不必要なフラッシングを避けるために 'out << '\ n';' '' 'operator <<'で 'out << endl;'をスワップします。 – user4581301

答えて

2

問題は、あなたの代入演算子が現在Matrixconst非参照を取ることです。ただし、(a1+a4)は、以外の-constの参照にバインドできない一時オブジェクトを生成します。コードをコンパイルするには、次の修正を参照してください。

#include<iostream> 
using namespace std; 

//write your code here 
class Matrix{ 
    private: 
    int arr[3][3]; 
    public: 
    friend istream& operator >> (istream& in,Matrix &matrix); 
    friend ostream& operator << (ostream& out,const Matrix& matrix); 
    friend Matrix operator + (Matrix &a,Matrix &b); 
    void setArr(int i,int j,int data){ 
     arr[i][j] = data; 
    } 
    int getArr(int i,int j) const{ 
    //      ^^^^^ // Added const 
     return arr[i][j]; 
    } 
    Matrix& operator = (const Matrix &b); 
    //     ^^^^^ // Added const 
}; 
istream& operator >> (istream& in,Matrix &matrix) 
{ 
    for(int i=0;i<3;i++) 
     for(int j=0;j<3;j++) 
      in >> matrix.arr[i][j]; 
    return in; 
} 
ostream& operator << (ostream& out,const Matrix &matrix){ 
    for(int i=0;i<3;i++) 
    { 
     for(int j=0;j<3;j++) 
      out << matrix.arr[i][j] << " "; 
     out << endl; 
    }  
    return out; 
} 
Matrix operator + (Matrix &a,Matrix &b){ 
    Matrix temp; 
    for(int i=0;i<3;i++) 
     for(int j=0;j<3;j++) 
      temp.setArr(i,j,(a.getArr(i,j)+b.getArr(i,j))); 
    return temp; 

} 
Matrix& Matrix::operator = (const Matrix &b){ 
//       ^^^^^ // Added const 
    for(int i=0;i<3;i++) 
     for(int j=0;j<3;j++) 
      arr[i][j] = b.getArr(i,j); 
    return *this; 
} 
int main() 
{ 
    Matrix a1,a2,a3,a4; 
    cin >> a1; 
    cin >> a2; 
    a4 = a2; 
    a3 = (a1+a4); // No errors now 
    cout << a1 << endl; 
    cout << a2 << endl; 
    cout << a3 << endl; 
    return 0; 
} 

Live example

注:getArr関数は代入演算子にconst Matrix&パラメータで呼び出すことができるように、constの正しい作らなければなりませんでした。

+0

私も暖かい答えについて2つの質問があります。最初に、テンポラリーオブジェクトは"Matrix&operator =(const Matrix&b)"にconstを追加する必要があります。 –

+0

次にgetArr関数は、安全にconstを作成するためのものですか? –

+0

一時オブジェクトは*本当に*定数ではありませんが、一時オブジェクトで「非constへの参照」を取る関数を呼び出せないというルールがあります。これは、呼び出された関数が引数に変更を加えた後に一時的なものが消えるときの驚きを防ぐためです。 –

1

あなたの問題は2つのものの組み合わせに起因します。まず、エラーが発生した行を見てみましょう:

a3 = (a1+a4); 

したがって、加算の結果を割り当てようとします。さんはoperator+の宣言を見てみましょう:

friend Matrix operator + (Matrix &a,Matrix &b); 

あなたが値ごとに新しいMatrixオブジェクトを返します。それは行うには正しいことだが、原因あなたのoperator=が間違って宣言されているどのように私たちをかむ終わる:

Matrix& operator = (Matrix &b); 

問題は、引数の型Matrix &です。我々はoperator+から値を返すので、私たちは一時的なオブジェクトで終わります。しかし、非constリファレンスを一時的にバインドすることは許されておらず、実際には一時的でない参照を介して一時的なものを変更することは意味がありません。

変更宣言と定義の両方:

Matrix& operator = (const Matrix &b); 

、それが動作するはずです、あなたが誤って代入の右辺を変更したくないとして、それはまた、理にかなっています。


アップデートはコメントで質問をフォローアップします

私が使用してお勧めしたいconst参照として引数を取るが、非として返された値を保つある

friend Matrix operator +(const Matrix &a,const Matrix &b); 

const

  1. constを参照する理由は、エラーを防ぐのに役立ち、可能な限り使用したいということです。たとえば、値を変更する予定のない関数にif (a ==b)の代わりにif (a = b)を誤って書き込んだ場合は、constという素晴らしいエラーが発生します。 constなしでは、誤って値を変更した場所を検索する必要があります。

  2. 非constとして返すように理由は、あなたが非constとして値を返し、ここで最適化することができる場合にのみ動作しmove semanticsを利用することです。また返される一時的なものはconstではありません。それは言語の観点からnon-constへの参照にバインドするだけでは意味がありません。

+0

テンポラリオブジェクトは定数オブジェクトなので、 "Matrix&operator =(const Matrix&b)"にconstを追加する必要がありますか?より良い "友人const行列演算子+(行列&a、行列&b);" –

+0

@ L.Maple私は非常に長いので、私の答えの最後にフォローアップのセクションで編集 –

+0

はい、私はそれを持っています多くは –

関連する問題