简体   繁体   中英

Overloaded operator C++: Object = Object * Object

I'm having trouble multiplying objects using the overloaded * operator

In the class I have the operator defined as:

const Matrix operator*(Matrix& B);

The implementation is

const Matrix Matrix::operator* (Matrix& B){
   Matrix r = Matrix(B.M,B.N);

   for(int i = 0; i < r.M; i++){
       for(int j = 0; j < r.N; j++){
        r.data[i*N+j] = (*this)(i,j) * (int)B(i,j);
       }
   }
   return r;
}

When I call

 Matrix C = A * B

I will get the expected result, however calling

C = C * C

Results in an error.

I'm guessing it's to with the calling object C but I'm not sure what to do!

EDIT:

My assignment operator. Matrix R is a deep copy.

Matrix Matrix::operator=(Matrix& B){
Matrix r(M,N);

for(int i = 0; i < M; i++){
    for(int j = 0; j < N; j++){
        r.data[i*N+j] = B(i,j);                                 
    }
}
return r;

}

The error is because you are storing your data in a variable called "data" (which is an int[] on the heap) and you haven't overridden your assignment operator to copy the values from the object being copied into the current member variable "data". So, the default assignment operator will copy the "data" pointer for you, which in your case is from a temporary value that will be out of scope after the assignment. Your destructor will most likely delete the "data" variable you are now pointing to because the temporary goes out of scope.

You have defined your own copy constructor to establish the "data" variable on the heap. The first example you have where Matrix C = A * B will use that copy constructor, which works.

The second example uses the default assignment operator, which will only copy the data pointer from the temporary value returned from the operation. Thus, you basically have no value that data is pointing to.

You have to define an assignment operator to make this work.

Here are suggested functions to go along with your copy constructor:

void Matrix::swap(Matrix& other)
{
   std::swap(M, other.M);
   std::swap(N, other.N);
   std::swap(data, other.data);
}

Matrix& Matrix::operator= (Matrix matrix)
{
   swap(matrix);
   return *this;
}

Matrix Matrix::operator* (const Matrix& B)
{
   Matrix r = Matrix(B.M,B.N);

   for(int i = 0; i < r.M; i++){
       for(int j = 0; j < r.N; j++){
        r.data[i*N+j] = (*this)(i,j) * (int)B(i,j);
       }
   }
   return r;
}

This works well because the copy constructor will be used for "matrix" in assignment operator (operator=). Then, the swap function will trade the "data" array with the temporary copy of Matrix. Therefore, you will copy the appropriate "data" from the operation*'s temporary variable.

This has nothing to do with "calling object C".

The first version

Matrix C = A * B;

uses constructor(s) or class Matrix to initialize new object C .

The second version

C = C * C;

uses assignment operator of class Matrix to assign new value to an existing object C .

You managed to screw up the assignment operator declaration/implementation somehow (which you don't show in the code you posted), which is why the second version does not compile.

There are problems with your operator * declaration as well. Even if you want to have it as class member, a more meaningful way to declare it would be

Matrix Matrix::operator* (const Matrix& B) const {
  ...

Note how const qualifiers are placed.

EDIT: So, here's your problem. Your assignment operator is completely broken.

Firstly, you declared your assignment operator as

Matrix Matrix::operator=(Matrix& B)

This operator cannot accept temporary objects on the right-hand side because you failed to declare the parameter as const . Non-const references cannot be bound to temporary objects. And in C = C * C the right-hand side of assignment is actually a temporary object produced by * operator.

Redeclare your assignment operator as

Matrix &Matrix::operator=(const Matrix& B)

Note, it accepts a const reference and returns a reference.

Secondly, your assignment operator is supposed to assign to *this , not to some standalone temporary object. And it is supposed to return a reference to *this . In other words, the implementation should be something along the lines of

Matrix &Matrix::operator=(const Matrix& B){

  // Resize `*this` to match the size of `B`

  for(int i = 0; i < M; i++){
    for(int j = 0; j < N; j++){
        this->data[i*N+j] = B(i,j);                                 
    }
  }
  return r;
}

Try to define the operator like this:

Matrix operator* (const Matrix& x, const Matrix& y)
{
    //...
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM