0
votes

I have been given the following code in my test file to implement:

cout << "Testing the Matrix constructors:" << endl;

cout << "Case 1: Creating a 2x4 matrix of zeros with the standard constructor:" << endl;
{
    Matrix matrix(2, 4);
    cout << matrix << endl;

Currently my code in my .cpp file for the constructor is as follows:

Matrix::Matrix (const int noOfRows, const int noOfCols){

double **p_matrix = new double*[noOfRows];
for(int i=0; i< noOfRows; i++){
    p_matrix[i] = new double[noOfCols];
}

for(int i=0; i< noOfRows; i++){
    for(int j=0; j<noOfCols; j++){
        p_matrix[i][j] = 0;
    }
}

My main confusion is the cout<< matrix part of the code as I could print out my 2x4 matrix within my constructor without needing this line. However, I have been asked to include cout<< matrix and I'm not sure I understand how it is meant to work. Is it calling my object matrix? And if so, how do I return my 2D array p_matrix since I'm not able to return a value from a constructor?

I thought one solution might be to overload my << operator as shown below:

std::ostream& operator<<(std::ostream& output, const Matrix& rhs){
output << rhs.data << std::endl;
return output; }

The reason I put rhs.data is because I tried rhs.matrix and rhs.p_matrix but got an error that a member variable was needed. Within my .h file, the only member variables I'm allowed are as follows:

  1. int noOfRows: the member variable that stores the number of rows
  2. int noOfColumns: the member variable that stores the number of columns
  3. double *data: the member variable that stores the address to the 1-D array of the matrix entries arranged column-wise, i.e., 1st column followed by the 2nd column and so on and so forth
  4. int GetIndex (const int rowIdx, const int columnIdx) const: the member function that determines the position (index) along the 1-D array (data) of a matrix entry in the row specified by rowIdx and the column specified by columnIdx.

I'm unsure how I can use operator overloading using only these variables so is this the best solution or is there an alternative way? Considering the limitations that I can't change my test file or the 4 member variables

1

1 Answers

1
votes

As you say:

Within my .h file, the only member variables I'm allowed are ... double *data: the member variable that stores the address to the 1-D array of the matrix

So, Matrix constructor should initialize data attribute, not a local double **p_matrix variable (then leaving data uninitialized)...

Simply replace:

Matrix::Matrix (const int noOfRows, const int noOfCols)
{
    double **p_matrix = new double*[noOfRows];
    for(int i=0; i< noOfRows; i++){
        p_matrix[i] = new double[noOfCols];
    }

    for(int i=0; i< noOfRows; i++){
        for(int j=0; j<noOfCols; j++){
            p_matrix[i][j] = 0;
        }
    }
}

By:

1. If your data attribute is a double**

Matrix::Matrix (const int noOfRows, const int noOfCols)
{

    this->noOfRows = noOfRows;
    this->noOfCols = noOfCols; 

    data = new double*[noOfRows];
    for(int i=0; i< noOfRows; i++){
        data[i] = new double[noOfCols];
    }

    for(int i=0; i< noOfRows; i++){
        for(int j=0; j<noOfCols; j++){
            data[i][j] = 0;
        }
    }
}

Later, you can do:

std::ostream& operator<<(std::ostream& output, const Matrix& rhs)
{
    for( int i=0; i< noOfRows; i++){
        for( int j=0; j < noOfCols; j++){
            output << rhs.data[i][j] << " "; // next column
        }
        output << std::endl; // next line
    }
    return output; 
}

2. If your data attribute is a double*

Matrix::Matrix (const int noOfRows, const int noOfCols){

    this->noOfRows = noOfRows;
    this->noOfCols = noOfCols;

    data = new double[noOfRows*noOfCols];
    for(int i=0; i< noOfRows*noOfCols; i++){
        data[i] = 0;
    }
}

Later, you can do:

std::ostream& operator<<(std::ostream& output, const Matrix& rhs)
{
    for( int i=0; i< noOfRows; i++){
        for( int j=0; j < noOfCols; j++){
            output << rhs.data[noOfCols*i+j] << " "; // next column
        }
        output << std::endl; // next line
    }
    return output; 
}

In both cases, make sure data is public in your header file, or make operator<<(std::ostream& output, const Matrix& rhs) be a friend of Matrix (or add a getter).

By the way, note that matrix are commonly stored as a double* rather than double**.