1

I do not know why the error after the definition of the operator overload function.the error is : no match for 'operator=' (operand types are 'Matrix' and 'Matrix'),a1+a4 after operator + overload function is only one matrix object that returns.so here should be a1 = object matrix?

#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;
}
L.Maple
  • 111
  • 3
  • 11
  • What if you use `Matrix& Matrix::operator=(const Matrix& b) { ... }`? **Notice the use of `const` for the parameter**. – James Adkison Apr 30 '16 at 00:54
  • Besides what's already been said, the `operator+()` should probably also take constant references as arguments, since it's not supposed to modify its operands. In its current form, you'd also be prevented from doing something like `a4=a1+a2+a3`. – Paulo1205 Apr 30 '16 at 01:14
  • This is a pretty good Matrix class. I'd replace all of the `3`s with `size` (defined `constexpr size_t size = 3;`) to kill off the magic number, add an `int & operator() (int row, int column)` to provide access to cells and swap `out << endl;` for `out << '\n';` in `operator <<` to avoid unnecessary flushing to round it out. – user4581301 Apr 30 '16 at 01:41
  • As well as the good suggestions elsewhere, I would comment that the idiomatic way to do this in C++ is to write `operator +=` as a member function (with an inner loop of `arr[i][j] += b.getArr(i,j)`, and then write `operator +` in terms of that. `Matrix operator + (Matrix lhs,const Matrix &rhs){ lhs += rhs; return lhs; }`. Note that the lhs argument is passed by *value* so that it is a temporary copy which you can then modify. – Martin Bonner supports Monica May 03 '16 at 07:49

2 Answers2

2

The problem is that your assignment operator currently takes a non-const Matrix reference. However, (a1+a4) generates a temporary object which cannot be bound to a non-const reference. See the following fixes to get your code compiling.

#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

Note: The getArr function had to be made const correct so that it could be called by the const Matrix& parameter in the assignment operator.

James Adkison
  • 9,412
  • 2
  • 29
  • 43
  • i also have 2 questions about your warm answer.First, is the tempory object a constant object so that "Matrix& operator = (const Matrix &b)" must add the const. – L.Maple May 03 '16 at 06:27
  • Then is the getArr function just for the sake of safe to be made const? – L.Maple May 03 '16 at 06:33
  • The temporary object isn't *really* constant, but there is a rule that you can't call functions that take "reference to non-const" with a temporary object. This is to prevent surprises when the called function makes changes to the argument, and then the temporary disappears. – Martin Bonner supports Monica May 03 '16 at 07:43
  • Once you have `operator =` taking a reference to const, then you can't call `b.getArr` unless `getArr` is a const function - the rules of the language don't allow it. (As a general rule, use `const` everywhere you possibly can. It makes it easier for you and the compiler to reason about the program.) – Martin Bonner supports Monica May 03 '16 at 07:45
1

Your problem stems from a combination of 2 things. Let's first look at the line the error occurs:

a3 = (a1+a4);

So it tries to assign the result of an addition. Let's look at the declaration for the operator+:

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

You return a new Matrix object per value. That's the right thing to do but ends up biting us due to how your operator= is incorrectly declared:

Matrix& operator = (Matrix &b);

The problem is with the argument type Matrix &. Since we return per value from the operator+ we end up with a temporary object. But binding a non-const reference to a temporary isn't allowed, and in fact it doesn't make sense to change temporaries through a non-const reference since they'll just be discared anyways.

change both the declaration and definition to:

Matrix& operator = (const Matrix &b);

and it should work, it also makes sense as you never want to accidentally change the right hand side of an assignment.


Update to follow up question in comment:

I'd suggest using

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

That is take the arguments as const references but keep the returned value as non-const.

  1. The reason to take the arguments as const references is that it can help prevent errors and you want to make use of it as much as you can. For example if you accidentally wrote if (a = b) instead of if (a ==b) in a function that isn't supposed to modify the values, you'd get a nice error with const. Without const you'd have to search around looking where you accidentally changed the value.

  2. The reason to return as non-const is to make use of move semantics which only work if you return a value as non-const and could be an optimization here. Also the temporary returned isn't const it just doesn't make sense to bind it to a non-const reference from the languages point of view.

Community
  • 1
  • 1
AliciaBytes
  • 7,300
  • 6
  • 36
  • 47
  • Is the tempory object a constant object so that "Matrix& operator = (const Matrix &b)" must add the const ? If so, would it be better to add "friend const Matrix operator +(Matrix &a,Matrix &b);" – L.Maple May 03 '16 at 07:03
  • @L.Maple I edited in a follow up section at the end of my answer as it got quite long. – AliciaBytes May 03 '16 at 07:26