Problem with Operator Overload

Im programming with Visual Studio 2010 at school and the code has worked perfectly in Windows 7 (and i was kinda proud of it). Now i went home to my fedora system with g++ and the compiler wont even compile it. I get the following error massage:

matrix-class-test.cpp: In function 'int main()':
matrix-class-test.cpp:105:2: error: no match for 'operator=' (operand types are
'Matrix' and 'Matrix')
 c=a+b;
  ^
matrix-class-test.cpp:105:2: note: candidate is:
matrix-class-test.cpp:67:9: note: Matrix& Matrix::operator=(Matrix&)
 Matrix& Matrix::operator=(Matrix& m)
         ^
matrix-class-test.cpp:67:9: note:   no known conversion for argument 1 from 'Mat
rix' to 'Matrix&'


I have to do some other tasks with matrizes and i do not know how to fix it and why it has worked in the first place.

Would be really nice if someone could help me.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
#include <iostream>
#include <iomanip> //whitespaces in output (table)

class Matrix
{
    private:
		int rows, cols;
        double* mArr;

    public:

        Matrix(int irows, int icols); //initialise
        ~Matrix(); //deconstructor
		Matrix(Matrix &m); //copyconstructor

		int getrows();
		int getcols();

		double& operator()(int inrows, int incols);
		Matrix& operator=(Matrix& m);
};

Matrix::~Matrix() {
       delete [] mArr;
}

Matrix::Matrix(int irows, int icols) {
       rows = irows;
       cols = icols;
       // Function -> 2-D Array to 1D
       mArr = new double[rows * cols];

	   for (int i=0;i<rows*cols;i++) mArr[i] = 0;
}

double& Matrix::operator()(int inrows, int incols)
{
       // Array is linewise in rom
       return mArr[inrows-1 + rows * (incols-1)];
}

Matrix::Matrix(Matrix &m)
{
        cols = m.cols;
		rows = m.rows;

		mArr = new double[rows * cols];

		for (int cpy=0;cpy<(m.getcols()*m.getrows());cpy++)
		{
			mArr[cpy]=m.mArr[cpy];
		}
}

int Matrix::getrows()
{
	return rows;
}

int Matrix::getcols()
{
	return cols;
}

// operators

Matrix& Matrix::operator=(Matrix& m)
{
	if (this == &m) return *this;

	for(int i=1;i<=rows;i++) {
	for(int j=1;j<=cols;j++) {
		(*this)(i,j)=m(i,j);
	}
	}
	return *this;
}

Matrix operator+(Matrix& a, Matrix& b)
{
	Matrix c(a.getrows(),a.getcols());
	
	for (int i=1;i<=a.getrows();i++){
	for (int j=1;j<=a.getcols();j++){
		c(i,j)=a(i,j)+b(i,j);
	}
	}

	return c;
}

int main()
{
	Matrix a(2,2),b(2,2),c(2,2);

	a(1,1)=5;
	a(1,2)=8;
	a(2,1)=9;
	a(2,2)=4;
	b(1,1)=10;
	b(1,2)=12;
	b(2,1)=15;
	b(2,2)=1;

c=a+b;

std::cout << "matrix c is:" << std::endl;
for (int k=1;k<=c.getrows();k++)
{
	for (int i=1;i<=c.getcols();i++)
	{
		std::cout << std::setw(14) << c(k,i);
	}
std::cout << std::endl;
}

return 0;
}
operator+ returns a Matrix, but operator= wants a Matrix&. I'm not sure about the exact issue, something about not being able to make a reference from a temporary.

Anyway the solution is to correct your prototype for operator=. During an assignment, does the right hand side of the operator change? No:
Matrix& operator=( const Matrix& other );

Which creates a problem with operator() as it is not const correct. You need to make two operator(), one for non-const, and one for const:
1
2
double& operator()( const int row, const int column );
double  operator()( const int row, const int column ) const;
Line 105: a+b produces a temporary instance of Matrix (line 79 indicates return Matrix by value). You then attempt to pass this temporary instance by reference (see line 67). Apparently the Microsoft compiler is more forgiving about passing a temporary instance by value. Passing as a non-const reference indicates that you intend to modify the passed temporary.

Try changing the Matrix references to const references.
 
Matrix & Matrix::operator = (const Matrix & m)


Note: You'll need to change operator (int,int) to be a const function also.

edit: BTW, all your for loops are faulty. In C/C++ all arrays are indexed from 0, not 1.
Last edited on
Thank you very much for the help so far.

I tried to make the changes you mentioned and the compiler found some errors, but i try to work them out. Isnt it somewhat strange that it works in Visual Studio?
Which compiler goes wrong here?

*edit* It seems like i cannot get it to work. I cannot use this or *this with a const Matrix. I find it quite hard actually to understand what is going on and why. The problem seems to be the overload of the () operator. I do not really know how to do it as a const because it is not const. :(

*edit2* The for loops are correct i think because of how i defined the mArr[] 1D-array.
Last edited on
The issue is with const-correctness. All functions that are called with a constant object must be declared as const:
1
2
3
4
5
6
7
8
9
10
11
12
class Thing
{
  public:
  void not_constant( void ){}
  void constant( void ) const {}
};

void function( const Thing& thing )
{
  thing.not_constant(); // compile error
  thing.constant(); // all good
}


By declaring a function as constant, you ensure that you won't modify the object:
1
2
3
4
5
6
7
8
9
10
class Thing
{
  int value;

  public:
  void contstant( void ) const
  {
    value++; // compile error, can't modify object
  }
};


So, like I said, you will need two operator(), one for constant objects, and one for modifiable objects:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Matrix
{
  // stuff
  
  double& operator()( int x, int y )
  {
    return arr[ y * width + x ]; // or whatever
  }

  double operator()( int x, int y ) const
  {
    return arr[ y * width + x ];  // will return a copy rather than the reference
  }
};
Last edited on
Ah i see. Thank you so much for your help. *thumbs up*
Last edited on
Topic archived. No new replies allowed.