I am having trouble getting my addition overloading function too work properly and was wondering if I could get some help with it. The rest of the functions and constructors in the class are default and can not be changed for this project so regardless they are correct. This means the only problems I am having are with the operator overloading functions themselves. Thanks in advance.
Matrix.h:
class Matrix {
// models a matrix of two dimentions, i. e. rows and columns of values
public:
Matrix & operator=(const Matrix& m);
Matrix & operator+(const Matrix& m);
Matrix.cpp:
//not included are the default and copy constructors plus read and write
//functions, etc...
Matrix& Matrix::operator=(const Matrix& m) {
this->rows = m.rows;
this->cols = m.cols;
matrix = vector< vector<double> >(rows);
for (int r=0; r<rows; r++)
matrix[r] = vector<double>(cols);
for (int r=0; r<rows; r++)
for (int c=0; c<cols; c++)
matrix[r][c] = m.matrix[r][c];
return *this;
}
Matrix & Matrix::operator+(const Matrix& m) {
Matrix newMatrix;
newMatrix = vector< vector<double> >(rows);
if (this->rows != m.rows || this->cols != m.cols) {
newMatrix.rows = 0;
newMatrix.cols = 0;
return newMatrix;
}
else {
newMatrix.rows = m.rows;
newMatrix.cols = m.cols;
for (int r = 0; r < m.rows; r++) {
newMatrix.matrix[r] = vector<double>(m.cols);
}
for (int r = 0; r < m.rows; r++) {
for (int c = 0; c < m.cols; c++)
newMatrix.matrix[r][c] = matrix[r][c] + m.matrix[r][c];
}
return newMatrix;
}
}
Main.cpp:
//in main.cpp I am trying to do the following operation and then output the result:
e = a + b;
You're returning a reference to the temporary newMatrix
Instead, your addition operator should return the result by value.
The function signature should look like this:
Matrix operator+(const Matrix& m);
While assignment operators should return a reference to the left object (resp. *this), all other infix operators should return by value. They are most easily written using the respective compound-assignment operator like +=.
For those reason most infix non-assignment-operators are free functions.
General pattern for infix +:
template<typename T> inline const T operator(const T& a, const T& b) {
T c = a;
return c += b;
}
You do not want to have such infix-operators as member-functions, because that breaks symmetry.
Instead, just define the compound operator +=.
Related
i have this class
class Matrix
{
int size;
std::unique_ptr<std::unique_ptr<int[]>[]> val;
public:
Matrix(int size1)
{
size=size1;
val=std::make_unique< std::unique_ptr<int[]>[] >(size);
...
}
... move constructor,move assignment operator
Matrix& operator+(Matrix &m)
{
Matrix sumMatrix(size);
for ( int i = 0; i < size; ++i)
{
for (int j = 0; j < size; ++j){
sumMatrix.val[i][j]=this->val[i][j]+m.val[i][j];
}
}
return sumMatrix;
}
and main :
...
Matrix e=b+c;
std::cout<<"e="<<std::endl;
e.print();
and i have this error :
warning: reference to local variable 'sumMatrix' returned
[-Wreturn-local-addr]
Matrix sumMatrix(size);
Can someone please help me with this ??
Return by value, as you should for operator+ most of the time:
// vvv--Removed & vvvvv-----vvvvv--Const is more appropriate here
Matrix operator+(Matrix const &m) const { ... }
This will require a copy constructor, make sure to add that. Also note that you should probably collect your for-loop logic into an operator+= and simplify operator+ significantly while providing more functionality for the end-user:
Matrix& operator+=(Matrix const& m) {
for (int i = 0; i < size; ++i) {
for (int j = 0; j < size; ++j) {
//vvv--No need for this-> in C++
val[i][j] += m.val[i][j];
}
}
return *this;
}
Matrix operator+(Matrix const& m) const {
Matrix sumMatrix{m}; // requires a copy constructor.
sumMatrix += *this;
return sumMatrix;
}
Here is a simplified addition operator overload for matrices that I've wrote, but my IDE (Clion) does not recognise it when I'm trying to use it like this: m1 = m2 + m3, and says: "binary operator + can't be applied to the expressions of type 'Matrix' and 'Matrix' "
Matrix& Matrix::operator += (Matrix& m1)
{
for (int i = 0; i < m_rows; ++i)
for (int j = 0; j < m_cols; ++j)
m_matrix[i][j] += m1.m_matrix[i][j];
return *this;
}
Matrix& operator + (Matrix m1, Matrix& m2){ return m1+=m2; }
What do I have to fix here?
P.S. I have also defined custom copy and move constructors and an assignment operator:
Matrix::Matrix(const Matrix& m1)
: m_matrix{new double*[m1.rows()]},
m_rows{m1.rows()},
m_cols{m1.cols()}
{
for (int i = 0; i < m1.rows(); ++i) {
m_matrix[i] = new double[m1.cols()];
for (int j = 0; j < m1.cols(); ++j)
m_matrix[i][j] = m1.m_matrix[i][j];
}
}
Matrix& Matrix::operator = (const Matrix& m1){
Matrix matrix(m1.rows(), m1.cols());
for (int i = 0; i < m1.rows(); ++i)
for (int j = 0; j < m1.cols(); ++j)
matrix.m_matrix[i][j] = m1.m_matrix[i][j];
for (int i = 0; i < m_rows; ++i)
delete m_matrix[i];
delete m_matrix;
m_matrix = matrix.m_matrix;
m_rows = m1.rows();
m_cols = m1.cols();
return *this;
}
Matrix::Matrix(Matrix&& m1) noexcept
: m_matrix{m1.m_matrix},
m_rows{m1.m_rows},
m_cols{m1.m_cols}
{
for (int i = 0; i < m1.m_rows; ++i)
delete m1.m_matrix[i];
delete m1.m_matrix;
m1.m_rows = m1.m_cols = 0;
}
Just guessing, as you did not provide the header file... Can it be that you forgot to declare the operator+ in your header file?
class Matrix
{
// ...
};
Matrix operator+ (Matrix m1, Matrix const& m2); // just declared, not implemented!
If so, you are able to use the operator only from within the Matrix implementation file (and only after the implementation), as it is simply not known elsewhere...
Have a look at my changes, too: really important, I don't return a reference any more; doing so would return m1 (result of operator += as reference), which is a local variable, so you get a dangling reference and undefined behaviour as soon as using it!
Additionally, you won't change m2, so you easily can pass it as const reference (provided you do the same change for your operator+= within class Matrix), this gives you more flexibility.
The first, your global operator + for Matrix should not return a refferece, bacause in that case you can write smth like this:
Matrix m1,m2,m3;
m1+m2=m3;
and this is ill formed.
Furthermore, I guess this Matrix& operator + (Matrix m1, Matrix& m2){ return m1+=m2; } is a returning m1 which is not a reference.
Also make sure you get all you operator arguments as const references.
Im trying to to use operator overloading with both + and = operator on a matrix class which i created. either the constructor or destructor is causing a problem or it isn't either (though i grayed out each of them and both and the code seems to work). could someone please help me understand what is causing this strange behavior. when i try to create 3 matrixes a b and c then try a = b+c; it just fails.
header file
#ifndef MATRIX_H;
#define MATRIX_H;
using namespace std;
enter code here
class matrix
{
friend ostream& operator<< (ostream&, matrix &);
public:
matrix();
matrix(int,int); //constructor
matrix(const matrix&);//copy constructor
~matrix();
int getRow();
int getCol();
void setRow(int);
void setCol(int);
class arr1D{ //proxy class to allow the use of [][] operator
public:
arr1D(int* a):temp(a){}
int &operator[](int a){
return temp[a];
}
int *temp;
};
arr1D operator[](int a){
return arr1D(arr2[a]);
}
matrix& operator=(const matrix& );
matrix& operator+(const matrix& );
protected:
private:
int row , col;
int **arr2;
};
#endif // MATRIX_H
enter code here
cpp file
#include <iostream>
#include "matrix.h"
using namespace std;
matrix::matrix()
{
setCol(0);
setRow(0);
**arr2=0;
}
matrix::matrix(int x, int y) //matrix constructor creates x*y matrix and initializes to 0's
{
setCol(y);
setRow(x);
arr2 = new int * [getRow()];
if (arr2) {
for (int i = 0; i < getRow(); i++) {
arr2[i] = new int [getCol()];
};
};
for (int i=0; i<getRow();i++){
for (int j=0;j<getCol();j++){
arr2[i][j]=0;
};
};
}
matrix::matrix(const matrix &m){ //defines the copying constructor
row=m.row;
col=m.col;
arr2 = new int*[row];
for (int i=0; i<row; i++){
arr2[i] = new int[col];
}
for (int i=0; i<row; i++){
for (int j=0; j<col; j++){
arr2[i][j] = m.arr2[i][j];
}
}
}
matrix::~matrix(){ //defines the destructor
for (int i=0; i<row; i++){
delete[] arr2[i];
}
delete[] arr2;
}
int matrix::getRow(){ //getter for row
return row;
}
int matrix::getCol(){ // getter for col
return col;
}
void matrix::setRow(int x){ //setter for row
row=x;
}
void matrix::setCol(int x){ //setter for col
col=x;
}
ostream& operator<< (ostream& output, matrix& a){
int i,j;
for (i=0; i < a.getRow() ; i++){
for (j=0; j< a.getCol() ; j++){
output << " " <<a.arr2[i][j];
};
output << "\n";
};
return output;
}
matrix& matrix::operator=(const matrix& right)
{
if (this == &right) { // Same object?
return *this;
}
row = right.row;
col = right.col;
for (int i=0; i<row; i++)
{
for (int j=0; j<col; j++){
arr2[i][j]=right.arr2[i][j];
}
}
return *this ;
}
matrix& matrix::operator+(const matrix& right)
{
int row=right.row;
int col=right.col;
matrix result(row,col);
for (int i = 0; i < row; i++){
for (int j = 0; j < col; j++){
//cout<<"arr2[i][j]="<<arr2[i][j]<<endl;
//cout<<"right.arr2[i][j]="<<right.arr2[i][j]<<endl;
result.arr2[i][j]=(arr2[i][j] + right.arr2[i][j]);
//cout<<"result.arr2[i][j]="<<result.arr2[i][j]<<endl;
};
};
return result;
}
First, as the other answer pointed out, you are returning a reference to a temporary in your operator +. That is undefined behavior.
But instead of writing operator + in this fashion, what you should do is write operator += instead, and then in turn, write operator + in terms of operator +=. Since a programmer would expect += to also work for the matrix in addition to +, it makes no sense to leave out +=.
For operator +=, you would in this case return a reference to the current object.
So all we need to do is move the code in operator + to operator +=:
#include <exception>
//...
matrix& matrix::operator+=(const matrix& right)
{
if(row != right.row || col != right.col)
throw std::logic_error("Matrix not the same size");
for (int i = 0; i < right.row; i++)
{
for (int j = 0; j < right.col; j++)
arr2[i][j] += right.arr2[i][j]);
}
return *this;
}
Note that we return a reference to the current matrix, since += modifies the current matrix. Also note that we throw an exception on an illegal matrix being sent to +=. This IMO makes more sense than returning a legitimate matrix back on error. If the matrix is not the same size, the code should not try and return a matrix back.
Now operator + can be written in terms of +=:
matrix matrix::operator+(const matrix& right)
{
return matrix(*this) += right;
}
Believe it or not, that's it. All we did was create a temporary matrix and call += with the passed in argument. We return the result of this as a brand new matrix, just as we expect.
The other issue is the assignment operator. Given that you've written a copy constructor and destructor, and the copy constructor works without having to use the assignment operator, then the copy / swap idiom can be used to implement the assignment operator.
#include <algorithm>
//...
matrix& matrix::operator=(const matrix& right)
{
matrix temp(right);
std::swap(temp.arr2, arr2);
std::swap(temp.row, row);
std::swap(temp.col. col);
return *this;
}
All we did here was create a temporary matrix of the passed in object and swap out its contents with the current object's contents. When the temporary dies off at the return, the temporary destroys the old contents that were swapped out.
This method has the advantage of not only being very simple to implement (just a bunch of calls to std::swap), it is also exception safe. If there is an issue creating the temporary matrix, a std::bad_alloc exception would have been thrown, without messing up or altering any members of this. The issue with the other answer given, where you're deallocating the memory first before allocating the new memory, is solved by using the above technique.
I have a template class matrix and I try to override the + operation for different matrix. I want to override the operator in a derived class but have a few errors. In other words, I want to be able to do only A+B for 2 defined objects of matrix and not to to do a for loop.
Here is the code:
#include<iostream>
using namespace std;
template<class T>
class matrix
{
protected:
T **tab;
int row,col;
public:
matrix(int row,int col)
{
this->row = row;
this->col = col;
tab = new T* [col];
for(int i = 0; i < col; i++)
tab[i] = new T[row];
tab[0][0] = 100;
}
T& operator()(int i,int j)
{
return tab[i][j];
}
T operator()(int i,int j)const
{
return tab[i][j];
}
void operator=(const matrix& that)
{
for(int i = 0; i < col ; i++)
for(int j = 0; j < row ; j++)
tab[i][j] = that.tab[i][j];
}
matrix(const T& tab)
{
row = tab.row;
col = tab.col;
tab = new T* [col];
for(int i = 0; i < col; i++)
tab[i] = new T[row];
}
~matrix()
{
for(int i = 0; i < col; i++)
delete tab[i];
delete tab;
}
};
template<class T>
class Operations: public matrix<T>
{
T& operator+(matrix& tab1,matrix& tab2)
{
int i,j;
ligne = tab.ligne;
col = tab.col;
tab3 = new T* [col];
for(int i = 0; i < col; i++)
tab3[i] = new T[ligne];
for(i = 0; i < col; i++)
for(j = 0; j < ligne; j++)
tab3[i][j] = tab1[i][j]+tab2[i][j];
return tab3;
}
};
int main()
{
matrix<int> tab1(10,10);
matrix<int> tab2(5,5);
cout<<tab1(0,0)<<endl;
tab1(0,0) = 10;
cout<<tab2(0,0)<<endl;
tab2(0,0) = 5;
tab2 = tab1;
tab1(0,0) = 3;
return 0;
}
The class matrix works fine. It is when I added the Operations class that I got the following erros:
v2.cpp:65:15: error: declaration of ‘operator+’ as non-function
T& operator+(matrix& tab1,matrix& tab2)
^
v2.cpp:65:13: error: expected ‘;’ at end of member declaration
T& operator+(matrix& tab1,matrix& tab2)
^
v2.cpp:65:21: error: expected ‘)’ before ‘&’ token
T& operator+(matrix& tab1,matrix& tab2)
Can you please explain me the reason for those errors and how to correct them?
Thank you
EDIT
I'd like to implement the + operator as a member class function in the matrix, but I am getting an error message: Can you please tell me what is going wrong with the way I define operator+?
matrix operator+(const matrix& that)const
{
int i,j;
T** tab3;
tab3 = new T* [col];
for(int i = 0; i < col; i++)
tab3[i] = new T[row];
for(i = 0; i < col; i++)
for(j = 0; j < row; j++)
tab3[i][j] = that.tab[i][j]+tab[i][j];
return tab3;
}
operator+() is normally expected to either be a member of the class it acts on (and accept one argument) or be a non-member that accepts two arguments.
For example;
class matrix
{
public:
matrix operator+(const matrix &) const; // member version
};
or
class matrix
{
public:
friend matrix operator+(const matrix &, const matrix &);
};
matrix operator+(const matrix &, const matrix &);
Note that friendship is optional in the second case, if the matrix provides public member functions that the operator+() needs.
The two approaches cannot be mixed. If the compiler encounters a class with both forms of operator+(), it has no basis to prefer calling one over the other, and will reject code like c = a+b due to ambiguity.
It is not also possible for another class (like your Operations) to provide a non-static member function operator+() that accepts two arguments of type matrix. The error message you are getting about a "non-function" is referring to that (albeit the compiler vendor has used rather cryptic wording for the error message).
Also note that operator+() should generally return by value, rather than returning a reference. Returning a reference usually causes expression like c = a+b to work differently than expected - and (depending on what reference is returned) can cause the caller to exhibit undefined behaviour.
I think you're just supposed to overload the + operator for the matrix class
matrix& operator+(matrix& other){
....
}
You can therefor use it like :
matrix<type> a;
// initialise a
matrix<type> b;
// initialise b
matrix<type> c = a+b; // a+b <=> a.operator+(b);
I'm implementing my own matrix class in c++ to help me develop my understanding of the language. I read somewhere that if you've got a working += operator, to use it in your + operator. So that's what I've got:
template <class T>
const Matrix<T>& Matrix<T>::operator+(const Matrix<T> &R){
Matrix<T> copy(*this);
return copy += R;
}
And here is the += operator overload:
template <class T>
const Matrix<T>& Matrix<T>::operator+=(const Matrix<T> & second_matrix){
//Learn how to throw errors....
if (rows != second_matrix.getNumRows() || cols != second_matrix.getNumCols()){throw "Dimension mismatch.";}
int i,j;
for (i = 0; i < rows; i++){
for (j = 0; j < cols; j++){
data[i][j] += second_matrix.get(i,j);
}
}
return *this;
}
I can use the += just fine (eg, a += b; returns no errors). But calling the + operator (eg, a = b + c;) returns :
test.cpp.out(77055) malloc: *** error for object 0x300000004: pointer being freed was not allocated
Just for completeness, here's my destructor:
template <class T>
Matrix<T>::~Matrix(){
for (int i = 1; i < rows; i++){
delete[] data[i]; }
delete[] data;
}
I've been using C++ for a couple years on and off, and still have trouble sometimes keeping track of pointers. I hope that's normal...
Any help would be great. Thanks!
EDIT: here's my copy constructor. It was set to free the data arrays but i removed that. now I get segmentation faults.
template <class T>
Matrix<T>::Matrix(const Matrix<T>& second_matrix){
rows = second_matrix.getNumRows();
cols = second_matrix.getNumCols();
data = new T*[rows];
int i,j;
for (i = 0; i < rows; i++){
data[i] = new T[cols];
}
for (i = 0; i < rows; i++){
for (j = 0; j < cols; j++){
data[i][j] = second_matrix.get(i,j);
}
}
}
operator+() should not return a reference type as it is a new (locally declared) instance that holds the result of the operation.
This is how I have implemented such operators for a Matrix class, this is based on a Vector Class. Once you define some operators all other should be defined in terms of the simplest operators:
Matrix::Matrix(const Matrix& rMatrix) :
_iRows(rMatrix._iRows), _iColumns(rMatrix._iColumns), _pVector(0)
{
_pVector = new Vector[_iRows];
for (int i = 0; i < _iRows; i++) { _pVector[i] = rMatrix._pVector[i]; }
}
Matrix& Matrix::operator=(const Matrix& rMatrix)
{
if (this != &rMatrix)
{
if (0 != _pVector) { delete[] _pVector; pVector = 0; }
_iRows = rMatrix._iRows;
_iColumns = rMatrix._iColumns;
_pVector = new Vector[_iRows];
for (int i = 0; i < _iRows; i++) { _pVector[i] = rMatrix._pVector[i]; }
}
return *this;
}
Matrix& Matrix::operator+=(const Matrix& rMatrix)
{
*this = *this + rMatrix;
return *this;
}
Matrix Matrix::operator+(const Matrix& rMatrix) const
{
Matrix matrix(_iRows, _iColumns);
ValidateSizes(rMatrix);
for (int i = 0; i < _iRows; i++) { matrix._pVector[i] = _pVector[i] + rMatrix._pVector[i]; }
return matrix;
}
Matrix operator+(const Matrix& rMatrix, double dNum)
{
Matrix matrix(rMatrix._iRows, rMatrix._iColumns);
matrix.ValidateSizes(rMatrix);
for (int i = 0; i < matrix._iRows; i++) { matrix._pVector[i] = dNum + rMatrix._pVector[i]; }
return matrix;
}
Matrix operator+(double dNum, const Matrix& rMatrix)
{
return operator+(rMatrix, dNum);
}
bool Matrix::ValidateSizes(const Matrix& rMatrix) const
{
if (_iRows != rMatrix._iRows) { /* THROW EXCEPTION */ }
if (_iColumns != rMatrix._iColumns) { /* THROW EXCEPTION */ }
return true;
}
If this a matrix for 3D rendering/simulation I would recommend NOT dynamically allocating the memory like that. You can end up with the memory being spread all over the place which causes caching issues. It also leads to potential memory bugs.
template <typename T>
class Matrix
{
public:
T m_Data[4][4];
};
or if you want something non-4x4
template <typename T, unsigned int rows, unsigned int columns>
class Matrix
{
public:
T m_Data[rows][columns];
};
and then dynamically allocate the Matrix objects.