Call an Operator+ function inside the += operator function in C++ - c++

I have got this overloading + operator function below and I have to write another overloading += operator function. I was wondering if I can just call the + operator function inside the =+ operator function since essentially both the function are doing the same thing. If so, then what does the syntax for it look like?
Below is my + operator function. I'm trying to add 2 Dynamically allocated matrices.
Matrix Matrix::operator + (const Matrix & orig) const
{
int length = columns * rows;
try
{
if (rows != orig.rows || columns != orig.columns)
{
throw 1;
}
}
catch (int c)
{
if (c == 1)
{
cout << "Error. Check Matrix dimensions, they do not match." << endl;
}
}
Matrix x(rows, columns);
for (int i = 0; i < length; i++)
{
x.data[i] = data[i] + orig.data[i];
}
return x;
}
void Matrix::operator += (const Matrix & orig)
{
//just call the + operator function!
}

Yes you can, you could make your function return a Matrix:
*this = *this + orig;
return *this;

You can simply call the + operator as you would do it everywhere else. One operand here is of course the parameter orig while the other is the object you call the operator on itself, which is *this.
So you could just write:
*this = *this + orig
Whether it is wise to define operator+= using operator+ or if its better to do it the other way round is up to you and might depend on your implementation.
However it is usually a good idea to define the += operator as
Matrix& Matrix::operator+= (const Matrix & orig)
since you can then do things like
mat += otherMat += otherMat2;
for this, just return *this as Stefan Giapantzakis already pointed out.

It is easy: just do *this = *this + other.
However, often it is a better idea to write operator+= fully, then write operator+ in terms of += like this:
Matrix& Matrix::operator+=(const Matrix &rhs) {
try {
if (rows != orig.rows || columns != orig.columns)
throw "Error. Check Matrix dimensions, they do not match.";
} catch (char const* msg) {
std::cout << msg << std::endl;
}
int length = columns * rows;
for (int i = 0; i < length; i++) {
data[i] += orig.data[i];
}
return *this;
}
friend Matrix operator+(Matrix lhs, Matrix const& rhs){
lhs += rhs;
return std::move(lhs);
}
which, as a bonus, reduxes a+b+c+d into creating exacly one matrix that is not move constructed.

Related

Why override operators aren't working with pointer?

I need to write a class Matrix with override operators + - * = and I've got some code that is works, but there is error.
//Matrix.h
template <class T>
class Matrix
{
public:
Matrix(int rows, int columns);
Matrix(const Matrix<T> &m);
Matrix<T>& operator=(Matrix<T>& m);
Matrix<T> operator+(Matrix<T>& m) const;
Matrix<T>* operator*(Matrix<T>* m);
};
template <class T> Matrix<T>& Matrix<T>::operator*(Matrix<T>& m) {
Matrix<T>* newMatrix = new Matrix<T>(rowCount, m.colCount);
for (int i = 0; i < rowCount; ++i)
{
for (int j = 0; j < m.colCount; ++j)
{
newMatrix->data[i][j] = 0;
for (int k = 0; k < colCount; ++k)
newMatrix->data[i][j] += data[i][k] * m.data[k][j];
}
}
return *newMatrix;
}
And override operators work fine in this code
Matrix<int> matrix(2, 2);
matrix = matrix + matrix;
//and other operators work fine here
But here it gives an error during compilation
Matrix<int>* matrix = new Matrix<int>(2, 2);
matrix = matrix + matrix;
matrix = matrix * matrix;
//etc
error
error C2804: binary "operator +" has too many parameters
Type information is crutal in C++.
This:
Matrix<int> matrix(2, 2);
matrix = matrix + matrix;
Here the type of matrix is Matrix. You have defined what the operator + for the type Matrix so this works fine.
This second one is different:
Matrix<int>* matrix = new Matrix<int>(2, 2);
matrix = matrix + matrix;
Here the type of matrix is Matrix*. Notice the star on the end of Matrix (this makes it a Matrix Pointer). This is a different type than above. You have not defined what operator + does for Matrix* so the compiler looks at its default operations and finds something close but not exact enough and generates an appropriate error message that tries to help.
To use the operator + you defined above you need to make sure the types of the values are Matrix and NOT Matrix*. You can covert a Matrix* into a Matrix by dereferencing the pointer via operator *.
Matrix<int>* matrix = new Matrix<int>(2, 2);
(*matrix) = (*matrix) + (*matrix);
Here: (*matrix) dereferences the Matrix* object and you get a Matrix. This can now correctly be applied to the operator + you defined above.
But saying all that.
That explains whay your problem is, but I don't think you actually want (or need) to use new in this context.
Dynamically allocating memory like this is probably not the correct way to implement this. It is usually better to use automatic variables (as this makes memory management easier).
template <class T>
Matrix<T> Matrix<T>::operator*(Matrix<T>& m)
// I also removed the & from the return value
// So that the value is copied out of the function.
// because with dynamic allocation the result will disappear
// after the function exits.
// Note: Though the matrix may be officially copied out
// the compiler is likely to optimize away this copy.
// and when you upgrade your class with move semantics
// then it will definitely be moved.
{
Matrix<T> newMatrix(rowCount, m.colCount);
// Remove the Pointer from the above line.
// And fix the -> into . in the code below.
for (int i = 0; i < rowCount; ++i)
{
for (int j = 0; j < m.colCount; ++j)
{
newMatrix.data[i][j] = 0;
for (int k = 0; k < colCount; ++k)
newMatrix.data[i][j] += data[i][k] * m.data[k][j];
}
}
return newMatrix;
// Now you can remove the * from the return value.
// The code works exactly the same.
// But you have not leaked the memory you allocated with `new`
}

Destructor is called in operator overloading [duplicate]

This question already has an answer here:
Overloading operator-() in C++
(1 answer)
Closed 6 years ago.
Here is my code. The problem is i'm assigning array of class to zero in destructor and when I do operator overloading in my program the destructor is called and my arrays are automatically assigned with 0.
//Overloading Plus Operator
Array Array::operator +(Array &obj)
{
for (int i = 0; i < 10; i++)
{
this->arr[i] = this->arr[i] + obj.arr[i];
}
return *this;
}
//Overloading Minus Operator
Array Array::operator -(Array obj)
{
for (int i = 0; i < 10; i++)
{
this->arr[i] = this->arr[i] - obj.arr[i];
}
return *this;
}
//Overloading Assignment Operator
void Array::operator =(Array &obj)
{
for (int i = 0; i < 10; i++)
{
arr[i] = obj.arr[i];
}
}
//Class Destructor
Array::~Array()
{
cout << "\n\nDeleting Object " << this->objNum << "\n";
for (int i = 0; i < 10; i++)
{
arr[i] = 0;
}
cout << "\n\n";
}
When you get stuck like this, it's sometimes a big clue that you're doing something wrong.
And you are.
The function you are implementing is operator+, whose meaning is generally that x+y should leave x and y unchanged and produce a new object whose value is their sum....
However, your implementation is more like that of x += y: an operation that changes the value of x to be the sum of its original value and y.
The problems you are seeing is a symptom of that mismatch.
As an aside, your functions are also const-incorrect — to repair this, for example, declare operator+ as
Array operator +(const Array &obj) const
In fact, if you had additionally declared an operator[] that was const correct and accessed the contents of the internal array accessed the contents of the array using this operator, the compiler would have clued you into the fact that you shouldn't be modifying the contents of the array in operator+.

operator = overload in template class

Im working on matrix template class, and now i should write the "=" operator overload.
What Im trying to do is to delete the matrix that appears in the left side of the '=', and return new one that equals to the matrix that appears in the right side of the '='.
because i can't delete "this" with a distructor, I delete it "manually" in the function. but now i should make a new matrix, therefor i make a new one ("temp") and return it.
The prblem is that "temp" is really return, but it doesn't set in the matrix that appears in the left side of the '='.
The code:
Matrix<int> m (3, 4);
Matrix<int> m2(2, 5);
m2 = m;
This was the main part.
The function:
template<class T>
Matrix<T> & Matrix<T>::operator=(Matrix<T>& mat)
{
if (this==&mat)
{
return *this;
}
for (int i = 0; i < this->rows; i++)
{
delete[] this->mat[i];
}
delete[] this->mat;
Matrix<T> * temp = new Matrix<T>(mat.rows, mat.cols);
for (int i = 0; i < temp->rows; i++)
for (int j = 0; j < temp->cols; j++)
{
temp->mat[i][j] = mat.mat[i][j];
}
return *temp;
}
template<class T>
Matrix<T>::Matrix(int row, int col)
{
rows = row;
cols = col;
mat = new T*[rows];
for (int i = 0; i < rows; i++)
{
mat[i] = new T[cols];
}
rester(*this);
}
Thx!!
Use std::vector as storage (instead of manal new and delete), and just accept the copy assignment operator generated by the compiler. It's that easy.
If you absolutely want to implement the copy assignment yourself, for learning, then just express copy assignment in terms of copy construction.
To do that, first define a noexcept swap operation:
// In class definition:
friend
void swap( Matrix& a, Matrix& b )
noexcept
{
using std::swap;
// swap all data members here
}
Then the copy assignment operator can be expressed as simply
// In class definition
auto operator=( Matrix other )
-> Matrix&
{
swap( *this, other );
return *this;
}
It's popular, an idiom, because it's very simple yet exception safe.
Instead of returning a reference, which adds verbosity and some possible marginal inefficiency for no gain, you might want to just use void as return type. However, probably for historical reasons, the containers in the standard library require the copy assignment operator to return a reference to self.
You need to allocate memory for this instead of creating a temp.
template<class T>
Matrix<T> & Matrix<T>::operator=(Matrix<T>& rhs)
{
if (this==&rhs)
{
return *this;
}
// Delete current memory
for (int i = 0; i < this->rows; i++)
{
delete[] this->mat[i];
}
delete[] this->mat;
this->rows = rhs.rows;
this->cols = rhs.cols;
// Allocate new memory
// Assign values to newly allocated memory.
this->mat = new int*[rhs.rows];
for (int = 0; i < rhs.rows; ++i )
{
this->mat[i] = new int[rhs.cols];
for (int j = 0; j < rhs.cols; j++)
{
this->mat[i][j] = rhs.mat[i][j];
}
}
// Return *this.
return *this;
}
I would recommend using the suggestion given in the answer by #Cheersandhth.
Also use a different name of the argument. Don't confuse with the member variable mat and the argument mat.

Program crashes at: (1) matrix multiplication; and (2) failed matrix addition/subtraction

In short, I was assigned the task of creating a class that dynamically allocates memory to form a matrix of int values.
Part of the class are member functions that perform the basic matrix calculations -- addition, subtraction, and multiplication. Everything compiles (on my end at least), but when I used a driver to test the multiplication portion, it keeps crashing.
I'm using Codeblocks as my IDE and haven't had much luck with the debugger there in trying to figure it out. It appears that the calculation completes (with correct values), but then things go horribly wrong somewhere.
For clarity, each object of the Matrix class has the following member data:
private:
int rows;
int cols;
int **element;
Below is a snippet of the implementation file in which the overloaded operator* is fleshed out. The portion where temp.element[i][x] is set to '0' before the loop performing the multiplication is commented out because the default constructor already sets all values to '0' -- which I had forgotten when I put it in originally. It didn't work when I didn't have it commented out either.
In testing, I used one 2x3 array and one 3x2 array.
Matrix Matrix::operator*(const Matrix &aMatrix) const
{
if(cols == aMatrix.rows)
{
Matrix temp(rows, aMatrix.cols);
for(int i = 0; i < rows; i++)
{
for(int x = 0; x < aMatrix.cols; x++)
{
//temp.element[i][x] = 0;
for(int n = 0; n < cols; n++)
{
temp.element[i][x] += (element[i][n]
* aMatrix.element[n][x]);
}
}
}
return temp;
}
else
{
cerr << "Matrix multiplication failed -- incompatible matrix sizes."
<< endl;
return *this;
}
}
Upon trying to go through the code and find errors, I started re-checking the other functions I had. It appeared that both addition and subtraction worked, but the program would close if the matrices were incompatible (ie. trying to add a 2x3 and a 4x4).
Below is the snippet for the addition (subtraction is almost identical just '-' instead of '+' in the final loops.
Matrix Matrix::operator+(const Matrix &aMatrix) const
{
if(rows == aMatrix.rows && cols == aMatrix.cols)
{
Matrix temp(rows, cols);
for(int i = 0; i < rows; i++)
{
for(int x = 0; x < cols; x++)
{
temp.element[i][x] = element[i][x] + aMatrix.element[i][x];
}
}
return temp;
}
else
{
cerr << "Undefined matrix addition -- matrices are different sizes."
<< endl;
return *this;
}
}
Any help or insight is appreciated. Thanks.
EDITED: Added overloaded assignment operator, copy constructor, and destructor code.
Below is the overloaded assignment operator:
Matrix Matrix::operator=(Matrix aMatrix)
{
if(this != &aMatrix)
{
for(int i = 0; i < rows; i++)
{
delete [] element[i];
element[i] = NULL;
}
delete [] element;
rows = aMatrix.rows;
cols = aMatrix.cols;
element = new int* [rows];
for(int i = 0; i < rows; i++)
{
element[i] = new int [cols];
for (int x = 0; x < cols; x++)
{
element[i][x] = aMatrix.element[i][x];
}
}
}
return *this;
}
Below is the copy constructor:
Matrix::Matrix(const Matrix &aMatrix)
{
rows = aMatrix.rows;
cols = aMatrix.cols;
element = new int* [rows];
for(int i = 0; i < rows; i++)
{
element[i] = new int [cols];
for (int x = 0; x < cols; x++)
{
element[i][x] = aMatrix.element[i][x];
}
}
}
Destructor:
Matrix::~Matrix()
{
for(int i = 0; i < rows; i++)
{
delete [] element[i];
element[i] = NULL:
}
delete [] element;
element = NULL;
}
You posted a copy constructor and assignment operator. Your assignment operator has 4 major issues:
You should pass the parameter by const reference, not by value.
You should return a reference to the current object, not a brand new object.
If new throws an exception during assignment, you've messed up your object by deleting the memory beforehand.
It is redundant. The same code appears in your copy constructor.
You can rewrite the assignment operator in terms of the copy constructor and alleviate these issues:
#include <algorithm>
//...
Matrix& Matrix::operator=(const Matrix& aMatrix)
{
Matrix temp(aMatrix);
swap(*this, temp);
return *this;
}
void Matrix::swap(Matrix& left, Matrix& right)
{
std::swap(left.rows, right.rows);
std::swap(left.cols, right.cols);
std::swap(left.element, right.element);
}
You just need to add the swap function to your Matrix class (probably as a private) function.
The code above uses the copy/swap idiom, and alleviates all of the issues I mentioned. This will work provided that your copy constructor and destructor are written properly. There are many threads on SO that talk about this idiom, but basically what is happening is this:
Create a temporary object from the passed-in object. If there is a problem with new throwing, your this doesn't get messed up.
Swap out this's members with the temporaries members. This refreshes the this object with the temporary's data, and gives the temporary the old data we don't need any more.
Let the temporary die with the old stuff we gave it from this.
Return this.
As to the other aspects, if the two Matrices cannot be multiplied, then just throw an exception. Do not return a bogus or confusing Matrix object that doesn't really reflect what happened.
In addition, you should first write operator += and *=. Why? Because implementing operator + and * can be done in terms of += and *=, respectively, plus you get the added bonus of having += and *= available.
For example:
Matrix& Matrix::operator+=(const Matrix &aMatrix)
{
if(rows != aMatrix.rows || cols != aMatrix.cols)
throw SomeException;
for(int i = 0; i < rows; i++)
{
for(int x = 0; x < cols; x++)
element[i][x] += aMatrix.element[i][x];
}
return *this;
}
Matrix Matrix::operator+(const Matrix &aMatrix)
{
Matrix temp(*this);
temp += aMatrix;
return temp;
}
So if the Matrix sizes are an issue, operator + and += will throw an exception. Note how operator + is implemented in terms of +=. Take the same approach to *, *=, and also - and -=.
You need to figure out what the syntax and semantics are of these operations. It looks from your example as though you want something like:
Matrix lhs = <something>;
Matrix rhs = <something>;
Matrix result = lhs * rhs;
to "just work". While this might be nice syntactically, you need to account for what happens if lhs and rhs can't be multiplied (or added, etc.) You also need to worry about setting up the result properly. You can't just return a "struct consisting of number of rows, columns and an array of pointers" and expect not to run into horrific memory management problems.
What will be responsible for making the product disappear? When it goes out of scope? C++ is not a very good language for linear algebra.
The first decision that you need to make is whether you intend to throw an exception for invalid operations, or return some indication of what went wrong, perhaps bool and a const char * to an error message.
Then you probably should try writing a function taking a result reference and 2 operand references, and just get the basic algebra right, if the matrices support the operation. (I have not mentioned yet that your Matrix is an integer matrix only.)
In "real life", you would probably try to find an open source standard solution that manages all of this, because numerical operations need to be managed very carefully.
One might even go so far as to suggest that this is a problem that has already been capably solved decades ago in Fortran, and to this day, if performance is an issue, there is a good chance that the underlying calculations might be in Fortran, or a library that was a port from C.

Operator overloading c++ advice

I am struggling to get my head around operator overloading. In this case the + operator I have and example of what I have tried, any help would be greatly appreciated.
I am getting an error which says "invaild use of 'class Matrix' I am unsure on how to fix this how can I add these two Matrix objects together?
Matrix Matrix::operator+(const Matrix& rhs){
return Matrix(Matrix + rhs.Matrix());
}
Matrix::Matrix(int MM, int NN){
M = MM;
N = NN;
data = new double[M * N];
for ( int i =0; i < M; i++)
{
for (int j = 0; j < N; j++)
{
data[i* N+j] = (double) 1000 + i*N+j;
// cout << data[i*N+j] <<"\t";
}
//cout <<"\n";
}
cout << "Matrix Constructor... (code to be implemented here!!!)\n";}
Thanks
rhs is a Matrix
calling a constructor like a method is very illegal
in Matrix + rhs, Matrix is not an identifier
Once you get your identifiers straightened out, *this + rhs is equivalent to this->operator+(rhs). It should be obvious from this that all you've done here is create an infinite recursion.
jpm's answer is very important to look at. Once you've fixed these things, you can look at mine.
Essentially, an operator overload is no different than any other function.
So, in the case of:
Matrix Matrix::operator+(const Matrix& rhs)
What you're really doing there is saying: add rhs to the current matrix, and return a new matrix. Your overload should not alter the current matrix. Help yourself and use a constant:
Matrix Matrix::operator+(const Matrix& rhs) const
A matrix addition like that should first check if the matrices have the same dimensions so that you can add them together, then loop through all "cells" and add them, and create a matrix out of that. For that, I'm guessing you'll need a second constructor, something like:
Matrix::Matrix(int MM, int NN, double values[])
{
M = MM;//TODO: change to width
N = NN;//TODO: change to height
data = new double[M*N];
for(int i < 0; i < M; i++)
for(int j < 0; j < N; j++)
data[i * N+j] = values[i * N+j];
}
return Matrix(Matrix + rhs.Matrix());
^^^^^^ ^^^^^^
You're using a type name (Matrix) where there should be an expression - that's what the compiler is complaining about. You're also trying to call the constructor on an existing object, which is invalid (and nonsensical). You also seem to be trying to implement operator+ in such a way that it calls itself; if you do somehow make it compile, then it will cause a stack overflow due to infinite recursion.
Perhaps the easiest way to implement addition is to implement operator+= to add one matrix to an existing one, and then implement operator+ in terms of that:
Matrix & Matrix::operator+=(Matrix const & rhs) {
// Perform addition here
for (int i = 0; i < N*M; ++i) {
data[i] += rhs.data[i];
}
return *this;
}
// This can be a non-member function
// Pass "lhs" by value to get a copy, then modify and return that.
Matrix operator+(Matrix lhs, Matrix const & lhs) {
return lhs += rhs;
}
// Or if you really want a member function for some reason
Matrix Matrix::operator+(Matix const & rhs) const {
return Matrix(*this) += rhs;
}
This does require you to have a correct copy constructor - since you're allocating memory yourself in the constructor, and presumably deallocating it in the destructor, you must implement a copy-constructor to correctly allocate new memory (per the Rule of Three), otherwise you'll get a double-deletion after copying a matrix.