Reputation: 109
Could somebody please explain me wth is wrong with my operators:
Matrix3D Matrix3D::operator*(Matrix3D& m) {
Matrix3D ret;
for(int i=0;i<4;i++) {
for(int j=0;j<4;j++) {
ret._data[i][j]=0.0;
for(int k=0;k<4;k++) {
ret._data[i][j] += (this->_data[i][k]*m._data[k][j]);
}
}
}
return ret;
}
Matrix3D& Matrix3D::operator=(Matrix3D& m) {
if(this==&m) {
return *this;
}
for(int i=0;i<4;i++) {
for(int j=0;j<4;j++) {
this->_data[i][j] = m._data[i][j];
}
}
return *this;
}
Matrix3D Matrix3D::Rotation(double ax, double ay, double az) {
Matrix3D rotX;
Matrix3D rotY;
Matrix3D rotZ;
rotX(
1, 0, 0, 0,
0, cos(ax), -sin(ax), 0,
0, sin(ax), cos(ax), 0,
0, 0, 0, 1
);
rotY(
cos(ay), 0, sin(ay), 0,
0, 1, 0, 0,
-sin(ay), 0, cos(ay), 0,
0, 0, 0, 1
);
rotZ(
cos(az), -sin(az), 0, 0,
sin(az), cos(az), 0, 0,
0, 0, 1, 0,
0, 0, 0, 1
);
// Matrix3D ret;
// ret = rotX*rotY*rotZ;
// This doesn't work
// C:\(...)\Matrix3D.cpp|100|error: no match for 'operator=' in 'ret = Matrix3D::operator*(Matrix3D&)(((Matrix3D&)(& rotZ)))'|
// however this does work
Matrix3D ret = rotX*rotY*rotZ;
return ret;
}
as stated in the code above, something like
Matrix3D ret;
ret = rotX*rotY*rotZ;
will result in
C:\(...)\Matrix3D.cpp|100|error: no match for 'operator=' in 'ret = Matrix3D::operator*(Matrix3D&)(((Matrix3D&)(& rotZ)))'|
compilation error, while something like
Matrix3D ret = rotX*rotY*rotZ;
will compile without any warning or error whatsoever (don't know if the matrixes are right tho, haven't checked that yet...).
Upvotes: 2
Views: 332
Reputation: 63872
operator*
and operator=
:Matrix3D Matrix3D::operator* (Matrix3D const& m) const;
Matrix3D& Matrix3D::operator= (Matrix3D const& m);
Your operator=
accepts a Matrix3D&
though rotX*rotY*rotX
will result in an rvalue and therefor you cannot bind a reference to it.
To make work your operator=
should accept a Matrix3D const&
, which can be bound to both lvalues and rvalues.
Even though it may look like Obj a = b
uses Obj::operator=
it's not, it'll use what is normally referred to as the copy-constructor. Read more about it here.
Upvotes: 5
Reputation: 523604
Actually, both operators are declared wrongly. They should take a const
reference to allow rvalues be accepted.
Matrix3D Matrix3D::operator*(const Matrix3D& m) const
// ^^^^^ ^^^^^
// this too, since you're not
// changing the LHS during '*'.
Matrix3D& Matrix3D::operator=(const Matrix3D& m)
// ^^^^^
You'll see that *
doesn't work with rotX*(rotY*rotZ)
.
The reason Matrix3D ret = rotX*rotY*rotZ;
compiles is because the operator=
is not invoked at all. It just calls the copy constructor of Matrix3D to the result of the multiplication. And the multiplication works because rotX * rotY * rotZ
is rewritten to
rotX.operator*(rotY).operator*(rotZ)
and rotY
and rotZ
are both lvalues, so they can be bound to Matrix3D&
.
Upvotes: 8
Reputation: 21818
Matrix3D& Matrix3D::operator=(Matrix3D& m)
You request that the right-side parameter is an l-value. It must be an existing variable, cannot be a temporary value. Consider using const Matrix3D& m
instead.
The Matrix3D ret = rotX*rotY*rotZ;
works because it is not using operator=
at all, instead it uses the default constructor Matrix3D::Matrix3D(const Matrix3D&)
.
Upvotes: 1
Reputation: 477434
Change the signature of the assignment operator to be const-correct:
Matrix3D& Matrix3D::operator=(Matrix3D const & m)
// ^^^^^
In your example code, the assignment operator wants to bind to a temporary, and temporaries cannot bind to non-constant references. By contrast, the copy constructor, which is invoked by the second piece of code, does accept a const reference, so there's no error.
Upvotes: 4