The spec says that the function must return the row of the matrix specified by the "row number" in []
Class Definition:
class Matrix
{
public:
//functions taken out
private:
double ** matrix; // the matrix array
unsigned rows; // # rows
unsigned cols; // # columns
};
The brief main:
cout << "Test []: " << endl;
try {
Matrix row = m0[0]; //**m0 is Matrix m0(1,1); where the constructor creates the appropriate array**
cout << row << endl;
row = m0[1];
cout << row << endl;
row = m0[100]; // should throw an exception
} catch (const char * err) {
cout << err << endl;
}
The Function implementation:
double& Matrix::operator [](const unsigned int &sub)
{
if( sub >= rows)
{
const char * error = "Error: invalid row index";
throw error;
} else
{
return *matrix[sub];
}
}
Overloaded << operator for display:
//This is working for my other displays so this shouldn't be the problem
ostream &operator << (ostream &ostrm, const Matrix &obj)
{
//Loop through to display
for(unsigned int i = 0; i < obj.rows; i++)
{
for(unsigned int j = 0; j< obj.cols; j++)
{
ostrm << setw(10) << setprecision(3) << obj.matrix[i][j];
}
ostrm << endl;
}
return ostrm;
}
Overloaded = operator:
//Again this works for everything else
Matrix& Matrix::operator=(const Matrix &rhs)
{
//Copy Rows and Cols
rows = rhs.rows;
cols = rhs.cols;
//If statement to check for self assignment
if(&rhs == this)
{
return *this;
}
else
{
delete [] matrix;
matrix = new double*[rows]; //Allocate Dynamic Array
//Deep copy elements by looping and copying each element
for(unsigned int i = 0; i < rows; i++)
{
matrix[i] = new double[cols];
for(unsigned int j = 0; j < cols; j++)
{
matrix[i][j] = rhs.matrix[i][j];
}
}
return *this;
}
}
My Output:
Test []:
Error: invalid row index
Expected Output:
Test []:
17.2 -3 -0.5 6
8.2 4 3 1
Error: invalid row index
I am uncertain as to why the rows are not displaying or possibly not even being stored.
Thanks in advance
Aside comment: your assignment operator is leaking memory: you delete matrix, but you need to delete also the individual rows (using the original value of rows)
for(unsigned int i = 0; i < rows; i++)
delete[] matrix[i];
Your operator[] should return a double[] or double *, not a double - you want to return a whole row, not a single value.
Your "test []" code should not even compile... Matrix row = m0[0]; assigns a double to a Matrix object.
Etc.
Bottom line: just use Eigen.
The first line is wrong.
operator[] is returning a double. You assign it to a Matrix. The Matrix is initialized with one value. You've taken out your Constructors. Which one is called? I assume, the called constructor initializes the rows and cols members with zero. When they're zero, the output stream operator does nothing.
I managed to find a solution that worked for my question. Below is what I implemented in case someone else has a similar problem.
Matrix temp(1, cols); //Calls my constructor here
for(unsigned int i = 0; i < 1; i++)
{
for(unsigned int j = 0; j < cols; j++)
{
temp.matrix[i][j] = matrix[sub][j]; //Accessed temp's matrix and assigned it with what is in the matrix that called the function
}
}
return temp;
Thank you to everyone who helped and added some input. Much appreciated
Related
I was creating a matrix class with overloaded operators in C++, I overloaded operators, << (output, with the ostream library), operator + that adds to matrices, operator = that's is used to assign one matrix to another. The problem is that when I use
cout<<m1+m2<<endl;
I get an error
E0349: No operator << matches these operands type are: std::ostream << Matrix
But if i do the following:
Matrix m = m1 + m2;
cout<<m<<endl;
it works perfect.
Here is the << operator:
ostream& operator<< (ostream &os,const Matrix& m)
{
if (m.isValid())
{
os << '|';
for (int i = 0; i < m.getRows(); i++)
{
for (int j = 0; j < m.getCols(); j++)
{
os << m.getMatrix()[i][j];
if (j < m.getCols() - 1)
{
os << ',';
}
}
os << '|';
}
}
else
{
os << "invalid matrix!";
}
return os;
}
The + operator:
Matrix Matrix::operator+ (Matrix &m)
{
Matrix* answer = new Matrix(m); //allocating space
if (valid && m.valid)//if they are both valid
{
if (colNum == m.colNum&&rowNum == m.rowNum) //if are from same size
{
answer->valid = true; //valid set to be true
for (int i = 0; i < rowNum; i++) //going over the matrix
{
for (int j = 0; j < colNum; j++)
{
answer->matrix[i][j] += matrix[i][j]; //adding data
}
}
}
else
{
//clearing data
delete answer;
answer = new Matrix();
}
}
else
{
//clearing data
delete answer;
answer = new Matrix();
}
return *answer;
}
And the = operator:
Matrix Matrix::operator= (Matrix &m)
{
int rows = m.rowNum; //putting cols and rows from the data
int cols = m.colNum;
if (m.valid)
{
matrix = new int*[rows]; //defining the matrix - first allocatin space for rows
for (int i = 0; i < rows; i++) //now allocating space for cols
{
matrix[i] = new int[cols];
}
for (int i = 0; i < rows; i++) //now going over the matrix and putting the data in
{
for (int j = 0; j < cols; j++)
{
matrix[i][j] = m.matrix[i][j];
}
}
}
//putting the rows and cols data
rowNum = m.rowNum;
colNum = m.colNum;
valid = m.valid; //setting to the right valid type
return *this;
}
and the class variables:
class Matrix
{
private:
bool valid;
int** matrix;
int rowNum;
int colNum;
There is a copy constructor a string constructor and a constructor that gets string input according to an algorithm and transforms it to a matrix.
You are actually faced with the fact that you Can't pass temporary object as reference (the link is to another question here on StackOverflow).
The solution in your case should be to replace:
ostream& operator<< (ostream &os,Matrix& m)
with:
ostream& operator<< (ostream &os,const Matrix& m)
as the overloaded operator signature. You currently expects an lvalue reference, In the case of
Matrix m = m1 + m2;
cout << m << endl;
that is what you're calling the function with m - a named variable and will outlive the execution of the command. In the failing case, you're calling the function with m1+m2 - the result of a plus operation, which is a temporary object. It just doesn't match your overload.
By the way - this change also makes sense because you're not modifying the matrix as you print it - you treat it as const.
I've been making a Matrix class over the course of the week and have run into a problem that has left me stumped: the return statement of one of my functions is throwing a bad_array_new_length exception!
Here's example code that I used to find this out:
Matrix Matrix::operator*(Matrix& mat)
{
if (this->columns != mat.rows)
{
//Do code if Matrix can't be multiplied.
}
else
{
Matrix result(this->rows, mat.columns);
//Multiply Matrices together.
//Print out result to prove the local Matrix works fine.
//It does.
try
{
return result;
}
catch (const exception& e)
{
cout << "return exception: " << e.what() << endl;
return result; //To be caught again in the test.
}
}
}
Low and behold, when I run the function it prints out "return exception: bad_array_new_length" onto the console.
The function was tested like so:
try
{
answer = A1 * B1; //A1 and B1 are able to be multiplied.
}
catch (const exception& e)
{
cout << e.what() << endl;
}
The test also catches the exception and prints it out as well.
After doing a little research, the bad_array_new_length exception is only thrown when an array is given an invalid length. The Matrix class does use a multidimensional array to store its doubles, but I would think that this isn't the root of the problem because the local Matrix works perfectly as intended.
Here is how the multidimensional array is declared and initialized in the constructor, just in case:
//Matrix.h
unsigned int rows;
unsigned int columns;
double ** storage = new double*[rows]; //Multidimensional array isn't completely formed, see the constructor.
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
//Matrix.cpp
Matrix::Matrix(unsigned int x, unsigned int y)
:
rows(x),
columns(y)
{
for (unsigned int i = 0; i < rows; ++i) //Completes the formation of the multidimensional array.
storage[i] = new double[columns];
for (unsigned int i = 0; i < rows; ++i)
{
for (unsigned int q = 0; q < columns; ++q)
{
storage[i][q] = 0; //Initializes each value in the array as 0.
}
}
}
/////////////////////////////////////////////////////////////////////////////////////////////////////
EDIT:
Here is the defined copy constructor and assignment operator:
Matrix::Matrix(const Matrix& obj)
{
rows = obj.rows;
columns = obj.columns;
for (unsigned int i = 0; i < rows; ++i)
{
for (unsigned int q = 0; q < columns; ++q)
{
storage[i][q] = obj.storage[i][q];
}
}
}
////////////////////////////////////////////////////////////////////////////////
bool Matrix::operator=(Matrix mat)
{
rows = mat.rows;
columns = mat.columns;
for (unsigned int i = 0; i < rows; ++i)
{
for (unsigned int q = 0; q < columns; ++q)
{
storage[i][q] = mat.storage[i][q];
}
}
return true;
}
Out of curiosity, I changed the code in the test to only be:
try
{
A1 * B1; //Removed assignment to answer Matrix.
}
catch (const exception& e)
{
cout << e.what() << endl;
}
..and the exception still threw as normal.
Fixed the issue, all I had to do was changed how memory was allocated in the class declaration and in the constructor.
I have a 2D array and I want to define a function that returns the value of the index that the user gives me using operator overloading.
In other words:
void MyMatrix::ReturnValue()
{
int row = 0, col = 0;
cout << "Return Value From the last Matrix" << endl;
cout << "----------------------------------" << endl;
cout << "Please Enter the index: [" << row << "][" << col << "] =" << ((*this).matrix)[row][col] << endl;
}
The operation ((*this).matrix)[row][col] should return an int.
I have no idea how to build the operator [][].
Alternatively, I could concatenate a couple of calls to the operator [], but I didn't succeed in it, because the first call to that operaror will return int* and the second one will return int, and it compel to build another operator, and I dont want to do that.
The data matrix is defined like
int** matrix; matrix = new int*[row];
if (matrix == NULL)
{
cout << "Allocation memory - Failed";
}
for (int i = 0; i < row; i++)//Allocation memory
{
matrix[i] = new int[col];
if (matrix[i] == NULL)
{
cout << "Allocation memory - Failed";
return;
}
}
What can I do?
Thank you,
Simply, such an operator does not exist, so you can not overload it.
A possible solution is to define two classes: the Matrix and the Row.
You can define the operator[] of a Matrix so that it returns a Row, then define the same operator for the Row so that it returns an actual value (int or whatever you want, your Matrix could be also a template).
This way, the statement myMatrix[row][col] will be legal and meaningful.
The same can be done in order to assign a new Row to a Matrix or to change a value in a Row.
* EDIT *
As suggested in the comments, also you should take in consideration to use operator() instead of operator[] for such a case.
This way, there wouldn't be anymore the need for a Row class too.
You can define your own operator [] for the class. A straightforward approach can look the following way
#include <iostream>
#include <iomanip>
struct A
{
enum { Rows = 3, Cols = 4 };
int matrix[Rows][Cols];
int ( & operator []( size_t i ) )[Cols]
{
return matrix[i];
}
};
int main()
{
A a;
for ( size_t i = 0; i < a.Rows; i++ )
{
for ( size_t j = 0; j < a.Cols; j++ ) a[i][j] = a.Cols * i + j;
}
for ( size_t i = 0; i < a.Rows; i++ )
{
for ( size_t j = 0; j < a.Cols; j++ ) std::cout << std::setw( 2 ) << a[i][j] << ' ';
std::cout << std::endl;
}
}
The program output is
0 1 2 3
4 5 6 7
8 9 10 11
I have no idea how to build the operator [][].
Sometimes it is fine to use a different operator, namely ():
int& Matrix::operator () (int x, int y)
{
return matrix[x][y];
}
const int& Matrix::operator () (int x, int y) const
{
return matrix[x][y];
}
int diagonal (const Matrix& m, int x)
{
return m (x, x); // Usage.
}
Advantage:
No need to use "intermediate" class like Row or Column.
Better control than with Row& Matrix operator (int); where someone could use the Row reference to drop in a row of, say, illegal length. If Matrix should represent a rectangular thing (image, matrix in Algebra) that's a potential source of error.
Might be less tedious in higher dimensions, because operator[] needs classes for all lower dimensions.
Disadvantage:
Uncommon, different syntax.
No more easy replacement of complete rows / columns, if that's desired. However, replacing columns is not easy, anyway, provided you used rows to model (and vice versa).
In either case, there are pros and cons if the number of dimensions are not known at runtime.
I was looking for self-tested array replacement...
Improved version returns reference or NULL reference and checks boundaries inside.
#include <iostream>
#include <iomanip>
template<typename T, int cols>
class Arr1
{
public:
Arr1(T (&place)[cols]) : me(place) {};
const size_t &Cols = cols;
T &operator [](size_t i)
{
if (i < cols && this != NULL) return me[i];
else {
printf("Out of bounds !\n");
T *crash = NULL;
return *crash;
}
}
private:
T (&me)[cols];
};
template<typename T, int rows, int cols>
class Arr2
{
public:
const size_t &Rows = rows;
const size_t &Cols = cols;
Arr2() {
ret = NULL;
for (size_t i = 0; i < rows; i++) // demo - fill member array
{
for (size_t j = 0; j < cols; j++) matrix[i][j] = cols * i + j;
}
}
~Arr2() {
if (ret) delete ret;
}
Arr1<T, cols>(&operator [](size_t i))
{
if (ret != NULL) delete ret;
if (i < rows) {
ret = new Arr1<T, cols>(matrix[i]);
return *ret;
}
else {
ret = NULL;
printf("Out of bounds !\n");
return *ret;
}
}
//T(&MemberCheck)[rows][cols] = matrix;
private:
T matrix[rows][cols];
Arr1<T, cols> *ret;
};
template<typename T,int rows, int cols>
class Arr
{
public:
const size_t &Rows = rows;
const size_t &Cols = cols;
T(&operator [](size_t i))[cols]
{
if (i < rows) return matrix[i];
else {
printf("Out of bounds !\n");
T(*crash)[cols] = NULL;
return *crash;
}
}
T (&MemberCheck)[rows][cols] = matrix;
private:
T matrix[rows][cols];
};
void main2()
{
std::cout << "Single object version:" << endl;
Arr<int, 3, 4> a;
for (size_t i = 0; i <= a.Rows; i++)
{
int *x = &a[i][0];
if (!x) printf("Fill loop - %i out of bounds...\n", i);
else for (size_t j = 0; j < a.Cols; j++) a[i][j] = a.Cols * i + j;
}
for (size_t i = 0; i < a.Rows; i++)
{
for (size_t j = 0; j <= a.Cols; j++) {
std::cout << std::setw(2) << a[i][j] << ' ';
if (a.MemberCheck[i][j] != a[i][j])
printf("Internal error !");
}
std::cout << std::endl;
}
std::cout << endl << "Double object version:" << endl;
Arr2<int, 3, 4> a2;
for (size_t i = 0; i < a2.Rows; i++)
{
for (size_t j = 0; j <= a2.Cols; j++) {
int &x = a2[i][j];
if (&x)
{
x++;
std::cout << std::setw(2) << a2[i][j] << ' ';
//if (&a2.MemberCheck[i][j] != &a2[i][j])
// printf("Internal error !");
}
}
}
}
Output
Single object version:
Out of bounds !
Fill loop - 3 out of bounds...
0 1 2 3 4
4 5 6 7 8
8 9 10 11 -858993460
Double object version:
1 2 3 4 Out of bounds !
5 6 7 8 Out of bounds !
9 10 11 12 Out of bounds !
it works fine in the program below
#include<iostream>
using namespace std;
class A{
public:
int r,c;
int** val;
A()
{
r=0;c=0;val=NULL;
}
A(int row,int col)
{
r=row;c=col;
int count=0;
val=new int*[row];
for(int i=0;i<r;i++){
val[i]=new int[col];
for(int j=0;j<c;j++){
count++;
val[i][j]=count;
}
}
}
int* &operator[](int index){
return val[index];
}
};
int main(void){
A a(3,3);
cout<<a[1][2];
return 0;
}
here, a[1][2] first computes a[1]-->which returns 2nd row as (int*) type
then it's read as (int*)[2] which returns 3rd element of that row.In short,
a[1][2]------>(a[1])[2]------>(val[1])[2]------>val[1][2].
This question already has answers here:
What is The Rule of Three?
(8 answers)
Closed 7 years ago.
I try to learn C++ basis in my free time and follow exercises of a book. Firstly, when I enter 9 as row and 8 as column I get malloc freeing error. Secondly, I get 0 as output I can't see what I enter. I want to write the program because I can reinforce rule of three. It's certainly not homework. Besides, I think it is hard question and efficient question. If the question can be answered, it will be helpful. Because I've searched on google I can't find out halfway decent thing about solution. Also, can you check my copy constructor, assignment operator and destructor and tell me where my errors at?
Write a class TwoD that implements the two-dimensional dynamic array
of doubles using ideas from this display in its constructors. You
should have a private member of type pointer to double to point to
the dynamic array, and two int (or unsigned int) values that are
MaxRows and MaxCols. You should supply a default constructor for which
you are to choose a default maximum row and column sizes and a
parameterized constructor that allows the programmer to set maximum
row and column sizes. Further, you should provide a void member
function that allows setting a particu- lar row and column entry and a
member function that returns a particular row and column entry as a
value of type double. Remark: It is difficult or impossible (depending
on the details) to overload [ ] so it works as you would like for
two-dimensional arrays. So simply use accessor and mutator functions
using ordinary function notation. Overload the + operator as a friend
function to add two two-dimensional arrays. This function should
return the TwoD object whose ith row, jth column element is the sum of
the ith row, jth column element of the left-hand operand TwoD object
and the ith row, jth column element of the right-hand operand TwoD
object. Provide a copy constructor, an overloaded operator =, and a
destructor. Declare class member functions that do not change the data
as const members.
My effort
#include <iostream>
using std::cin;
using std::cout;
using std::endl;
class TwoD
{
public:
TwoD();
TwoD(int row, int column);
void setRowCol();
double getVal(int row, int column);
friend const TwoD operator +(const TwoD& first, const TwoD& second);
int getterRow() const;
int getterCol() const;
void setterRow(int row);
void setterCol(int column);
TwoD(const TwoD& object);
TwoD& operator =(const TwoD& rightSide);
void putArr() const;
~TwoD();
static TwoD constructFromUserInput();
private:
int MaxRows;
int MaxCols;
double **arr;
};
int main(int argc, char const *argv[])
{
cout << "All size of TwoD object must be same\n\n";
TwoD arr1 = TwoD::constructFromUserInput();
TwoD arr2 = TwoD::constructFromUserInput();
TwoD arr3;
arr3 = arr1 + arr2;
TwoD arr4(arr3);
arr1.putArr();
arr2.putArr();
arr3.putArr();
arr4.putArr();
return 0;
}
void TwoD::setRowCol()
{
int r_user;
int c_user;
cout << "Enter num of rows => ";
cin >> r_user;
cout << "Enter num of columns => ";
cin >> c_user;
MaxRows = r_user;
MaxCols = c_user;
TwoD(MaxRows,MaxCols);
}
TwoD::TwoD(int row, int column)
: MaxRows(row), MaxCols(column)
{
arr = new double*[row];
for (int i = 0; i < row; i++)
{
arr[i] = new double[column];
}
for (int i = 0; i < MaxRows; i++)
{
for (int j = 0; j < MaxCols; j++)
{
cout << "Enter for " << i << j << "=> ";
cin >> arr[i][j];
}
}
}
TwoD::TwoD()
: MaxRows(2), MaxCols(2)
{
arr = new double*[2];
for (int i = 0; i < 2; i++)
{
arr[i] = new double[2];
}
}
double TwoD::getVal(int row, int column)
{
return arr[row][column];
}
const TwoD operator +(const TwoD& first, const TwoD& second)
{
TwoD sum;
for (int i = 0; i < first.MaxRows; i++)
{
for (int j = 0; j < first.MaxCols; j++)
{
sum.arr[i][j] = first.arr[i][j] + second.arr[i][j];
}
}
return sum;
}
TwoD::TwoD(const TwoD& object)
{
MaxRows = object.MaxRows;
MaxCols = object.MaxCols;
arr = new double*[MaxRows];
for (int i = 0; i < MaxRows; i++)
{
arr[i] = new double[MaxCols];
}
for ( int i = 0; i < MaxRows; i++ )
{
for ( int j = 0; j < MaxCols; j++ )
{
arr[i][j] = object.arr[i][j];
}
}
}
TwoD::~TwoD()
{
for (int i = 0; i < MaxRows; i++)
delete [] arr[i];
delete [] arr;
}
TwoD& TwoD::operator =(const TwoD& rightSide)
{
if (this == &rightSide)
{
return *this;
}
for (int i = 0; i < MaxRows; i++)
delete [] arr[i];
delete [] arr;
arr = new double*[rightSide.MaxRows];
for (int i = 0; i < rightSide.MaxRows; i++)
{
arr[i] = new double[rightSide.MaxCols];
}
MaxRows = rightSide.MaxRows;
MaxCols = rightSide.MaxCols;
for (int i = 0; i < MaxRows; i++)
{
for (int j = 0; j < MaxCols; j++)
{
arr[i][j] = rightSide.arr[i][j];
}
}
return *this;
}
void TwoD::putArr() const
{
for (int i = 0; i < MaxRows; i++)
{
for (int j = 0; j < MaxCols; j++)
{
cout << arr[i][j] << " ";
}
cout << endl;
}
}
int TwoD::getterRow() const
{
return MaxRows;
}
int TwoD::getterCol() const
{
return MaxCols;
}
void TwoD::setterRow(int row)
{
MaxRows = row;
}
void TwoD::setterCol(int column)
{
MaxCols = column;
}
TwoD TwoD::constructFromUserInput()
{
int r_user;
int c_user;
cout << "Enter num of rows => ";
cin >> r_user;
cout << "Enter num of columns => ";
cin >> c_user;
// Construct an object.
TwoD obj(r_user, c_user);
// Return the object
return obj;
}
your copy constructor creates the arrays, but never copies the contents.
The copy assignment operator does this correctly. For that matter, you have loads of duplicated new[] loops, a couple of delete[] loops, and you should have two copy loops. Factor these out into functions, and you only need to get them right once.
sum creates a default-sized object and then, probably, overruns both row and column dimensions. The usual (easy and correct) implementation is to create a local copy of the left-hand argument (using the copy ctor you fixed above) and forward to operator+=. That operator is much easier to get right.
you have a way of printing these matrices out. Do it! Do it everywhere! This makes it easy to see which stage things went wrong at.
this book doesn't sound very good. It's teaching poor practice for no obvious reason (the operator+ trick is standard, you should use unique_ptr if you can't use vector, etc. etc.)
Edits: I'll reply to some comments here because they're in danger of turning into a chat session, and I don't want to spend more time on this.
I have fixed copy constructor is it right?
This is a good time to figure out how to test and debug code. Add print statements, use a debugger, split things out into functions you can test and then write tests for them.
what you mean a couple of delete[] loops and having two copy loops
Look for loops in your code. I can see 3 loops calling new[], all doing essentially the same thing. I can see 2 loops calling delete[], one in the destructor and one in the copy assignment operator. Just search your own code for the for keyword!
I really don't find a way to print out matrices
so where did TwoD::putArr come from? Admittedly ostream& operator<<(ostream&, TwoD const &) would be a better name for it, but you wrote it so you might as well use it.
I can't get destructor into main()
you can't stop the destructor being called when main finishes - your objects go out of scope then. Just stick a breakpoint in the destructor and it will be called.
Because arr is private how can I test?
you can still see it in the debugger, you can still print the contents (as above), you can still call getVal from a unit test, you can just make it public until you've figured out your problem(s)
Problem with your code:
void TwoD::setRowCol()
{
int r_user;
int c_user;
cout << "Enter num of rows => ";
cin >> r_user;
cout << "Enter num of columns => ";
cin >> c_user;
MaxRows = r_user;
MaxCols = c_user;
///
/// This constructs a new TwoD object but does not change
/// object on which the function was invoked.
///
TwoD(MaxRows,MaxCols);
}
Ways to solve the problem:
Update the member data
void TwoD::setRowCol()
{
int r_user;
int c_user;
cout << "Enter num of rows => ";
cin >> r_user;
cout << "Enter num of columns => ";
cin >> c_user;
// Delete the current memory
for (int i = 0; i < MaxRows; i++)
{
delete [] arr[i];
}
delete [] arr;
MaxRows = r_user;
MaxCols = c_user;
// Allocate new memory.
arr = new double*[MaxRows];
for (int i = 0; i < MaxRows; i++)
{
arr[i] = new double[MaxCols];
}
// Now read the data.
for (int i = 0; i < MaxRows; i++)
{
for (int j = 0; j < MaxCols; j++)
{
cout << "Enter for " << i << j << "=> ";
cin >> arr[i][j];
}
}
}
Create a function that returns a brand new object
I recommend this method.
First, update the constructor that takes the row and the column so that it does not have any code to read data from user input.
TwoD::TwoD(int row, int column)
: MaxRows(row), MaxCols(column)
{
arr = new double*[row];
for (int i = 0; i < row; i++)
{
arr[i] = new double[column];
}
}
Second, add a static member function to construct an object from user input.
static TwoD constructFromUserInput();
and implement it as:
TwoD TwoD::constructFromUserInput()
{
int r_user;
int c_user;
cout << "Enter num of rows => ";
cin >> r_user;
cout << "Enter num of columns => ";
cin >> c_user;
// Construct an object.
TwoD obj(r_user, c_user);
// Now read the data.
for (int i = 0; i < r_user; i++)
{
for (int j = 0; j < c_user; j++)
{
cout << "Enter for " << i << j << "=> ";
cin >> obj.arr[i][j];
}
}
// Return the object
return obj;
}
Third, use the new function from main.
int main(int argc, char const *argv[])
{
cout << "All size of TwoD object must be same\n\n";
TwoD arr1 = TwoD::constructFromUserInput();
TwoD arr2 = TwoD::constructFromUserInput();
TwoD arr3;
arr3 = arr1 + arr2;
arr1.putArr();
arr2.putArr();
arr3.putArr();
return 0;
}
I overwrote a + operator:
Matrix& Matrix::operator+(Matrix m1)
{
//This should never be triggered
if(this->data.capacity() != m1.data.capacity() || this->data[0].capacity() != m1.data[0].capacity())
{
cout << "Dimensions don't match, can't add.\n";
throw 7;
}
vector<vector<double>> result;
result.resize(m1.data.capacity());
for(int i = 0; i < m1.data.size(); i++)
{
result[i].resize(m1.data[0].size());
for(int j = 0; j < m1.data[0].size(); j++)
{
result[i][j] = m1.data[i][j] + this->data[i][j];
}
}
return Matrix(m1.getRows(),m1.getCols(), result);
}
This is the corresponding Constructor:
Matrix::Matrix(int rows, int cols, vector<vector<double>> data)
{
this->rows = rows;
this->cols = cols;
this->data = data;
}
Here's the executing code:
c = (a+b);
When I assign a breakpoint at the last line of the operator overload, I can see the correct results in result and both cols and rows are assigned correctly. When I step out, c has "rows" and "cols" set correctly, but data is empty. Why is that?
Your operator + is wrong. It should be returning a new object, not a reference to a local object (which is UB anyway).