简体   繁体   中英

Overloading Operator *= and Operator+ in Matrix Template Class

The method template <class T> const Matrix<T> &Matrix<T>::operator*=(T rhs) for program matrix.cc should be able to returns calling object with matrix scaled by rhs, and the parameter rhs will be the same type as the matrix.

The error output that I am receiving from the compiler is:

[hw7] make clean && make bin/test_matrix_mul_assign && ./bin/test_matrix_mul_assign
rm -f bin/*
g++   -std=c++11   -Wall       -I inc   -I src   -c   src/test_matrix_mul_assign.cc -o bin/test_matrix_mul_assign.o
g++     bin/test_matrix_mul_assign.o   -o bin/test_matrix_mul_assign
Testing Matrix::operator*=
  Expected Matrix[0][0]: 2.0, Actual: 1
  FAILED

Could someone let me know why I receive this "Failed" output when I know I pass the // TEST MUL ASSIGMENT OP CORRECT RETURN section.

Here is my matrix.cc:

#include <matrix.h>

template <class T>
const Matrix<T> &Matrix<T>::operator*=(T rhs) {
  unsigned int rows_ = 0;
  unsigned int cols_ = 0;
  T **m_ = nullptr;

  for (unsigned int i = 0; i < rows_; ++i) {
    m_[i] = new T[cols_];
    for (unsigned int j = 0; j < cols_; ++j) {
      m_[i][j] = m_[i][j] * rhs;
    }
  }
  return *this;
}

template <class T>
const Matrix<T> Matrix<T>::operator+(const Matrix<T> &rhs) const {
  if (!(this->cols_ == rhs.cols_) && (this->rows_ == rhs.rows_)) {
    std::cout << "Cannont add matrices. Wrong dimensions\n";
    exit(0);
  }

  Matrix<T> lhs;
  lhs.rows_ = this->rows_;
  lhs.cols_ = this->cols_;

  for (unsigned int i = 0; i < lhs.rows; ++i) {
    for (unsigned int j = 0; j < lhs.cols_; ++j) {
      lhs[i] += rhs[i];
    }
  }
  return lhs;
}

Here is my matrix.h:

#include <cassert>
// using assert
#include <exception>
#include <iostream>

template <class T>
class Matrix {
 public:
  friend class MatrixTester;

  /* Times Equals Op: 1 Point
   *   Returns calling object with matrix scaled by rhs.
   *   Parameter:
   *    - rhs will be the same type as the matrix
   */
  const Matrix<T> &operator*=(T rhs);

  /* Add Op: 1 Point
   *   Returns the sum of calling object's matrix and rhs's matrix as a new
   *   object.
   * Precondition(s):
   *   - lhs rows must equal rhs rows
   *   - lhs cols must equal rhs cols
   */
  const Matrix<T> operator+(const Matrix<T> &rhs) const;

 private:
  T **m_;
  unsigned int rows_;
  unsigned int cols_;
};

#include <matrix.cc>  //NOLINT

This is my test_matrix_mul_assign.cc tester:

#include <test_matrix.h>

int main(int argc, char **argv) {
  MatrixTester tester;

  cout << "Testing Matrix::operator*=" << endl;
  if (tester.Test_MulAssignOp()) {
    cout << "  PASSED" << endl;
    return 0;
  }

  cout << "  FAILED" << endl;
  return 1;
}

bool MatrixTester::Test_MulAssignOp() const {
  const int kRows = 3, kCols = 4;
  Matrix<double> test_m;
  test_m.m_ = new double *[kRows];
  for (unsigned int i = 0; i < kRows; ++i) {
    test_m.m_[i] = new double[kCols];

    for (unsigned int j = 0; j < kCols; ++j)
      test_m.m_[i][j] = (i + 1.0) * (j + 1.0);
  }
  test_m.rows_ = kRows;
  test_m.cols_ = kCols;

  // TEST MUL ASSIGMENT OP CORRECT RETURN
  const Matrix<double> *m_ptr = &(test_m *= 2.0);
  if (m_ptr != &test_m) {
    cout << "  Expected return address of assigment: " << &test_m
         << ", Actual: " << m_ptr << endl;
    return false;
  }
  // TEST MUL ASSIGMENT OP CALCULATION
  if (test_m.m_[0][0] != 2.0) {
    cout << "  Expected Matrix[0][0]: 2.0, Actual: " << test_m.m_[0][0] << endl;
    return false;
  }
  if (test_m.m_[1][3] != 16.0) {
    cout << "  Expected Matrix[1][3]: 16.0, Actual: " << test_m.m_[1][3]
         << endl;
    return false;
  }
  if (test_m.m_[2][2] != 18.0) {
    cout << "  Expected Matrix[2][2]: 18.0, Actual: " << test_m.m_[2][2]
         << endl;
    return false;
  }
  return true;
}

You have the following variable definitions in the operator*= implementation:

unsigned int rows_ = 0;
unsigned int cols_ = 0;
T **m_ = nullptr;

They will shadow all of the members of the class. When you use rows_ , cols_ and m_ later in the function definition they will refer to these local variables, not the class members of the current instance.

Therefore effectively your implementation of operator*= does nothing at all. It is not surprising that the test for the correct value then fails.

Simply remove these declarations, so that the names will refer to the current instance's members instead.

Then there is also not going to be any point to m_[i] = new T[cols_]; . So remove that as well.


Why are there all of these dynamic allocations with new in the first place? This is seriously bad style and is going to cause you all kinds of issues. Use std::vector instead.


class Matrix also seems to be lacking a proper constructor. This again will cause all kinds of issues, especially when it leaves memory allocation to a user of the class.

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