For the following function that represents a matrix
class m // matrix
{
private:
double **matrix;
int nrows, ncols;
class p
{
private:
double *arr;
public:
p (double *a)
: arr (a)
{
}
double &operator[] (int c)
{
return arr[c];
}
};
public:
m (int nrows, int ncols)
{
this->matrix = new double *[nrows];
for (int i = 0; i < nrows; ++i)
{
this->matrix[i] = new double [ncols];
}
this->nrows = nrows;
this->ncols = ncols;
}
~m()
{
for (int i = 0; i < this->nrows; ++i)
{
delete [] this->matrix[i];
}
delete this->matrix;
}
void assign (int r, int c, double v)
{
this->matrix[r][c] = v;
}
p operator[] (int r)
{
return p (this->matrix[r]);
}
};
operator works for element access but does not work with element change. How can I add the functionality of assign() function to the operator?
Redefine your first accessor as
const p& operator[] (int r) const
and the one for setting as
p& operator[] (int r)
Then ensure that a value copy is not taken in either case. Returning a reference allows you to change the element value via the calling function.
Your p class is private and you won't be able to call operator [] on it.
Make p accessible, and in both operator [] implementations you should return by reference, not by value. This will allow you to modify original data, not the copy's.
Related
I got a class Matrix and a class Row. Matrix has as member variable a pointer to a pointer of an object from class Row. I overloaded the operator [] for Matrix and Row. But somehow the overloaded operator from Row is never getting called and I can't figure out why not.
Example Code:
matrix.h
class Row
{
int* value;
int size;
public:
int& operator[](int i)
{
assert(i >= 0 && i < size);
return value[i];
}
};
class Matrix
{
private:
Row **mat; // Pointer to "Row"-Vector
int nrows, ncols; // Row- and Columnnumber
public:
Row& Matrix::operator[](int i){
assert(i >= 0 && i < nrows);
return *mat[i];
}
Row** getMat() {
return mat;
}
// Constructor
Matrix(int rows, int cols, int value);
};
matrix.cpp
#include "matrix.h"
Matrix::Matrix(int rows, int cols, int value) : nrows(rows), ncols(cols){
mat = new Row*[rows];
for(int i = 0; i < rows; i++) {
mat[i] = new Row(ncols);
for(int j = 0; j < ncols; j++){
// the operator-overload of Row[] isn't getting called and I don't get why not
mat[i][j] = value;
}
}
}
int main(){
Matrix m = new Matrix(2, 2, 4);
return 0;
mat[i] gives you Row*, and you want to call Row::operator[], but pointer to Row is not dereferenced automatically. So you have to dereference it manually: (*mat[i])[j].
So I just figured it out myself.
I tried to call the []-operator from Matrix through mat[][], but since mat is a Row** Row& Matrix::operator[](int i) is never getting called.
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);
im working with simple 2D array,but in my copy constructor i encounter a problem.
Here's a excerpt from my code:
//default constructor
Matrix::Matrix(int r, int c)
{
rows = r;
cols = c;
mainArray = new int[rows*cols];
array = new int *[rows];
for (int i = 0; i < rows; i++)
array[i] = mainArray + (i*cols);
}
//at member
int& Matrix::at(int i, int j)
{
return array[i][j];
}
//copy constructor
Matrix::Matrix(const Matrix & obj)
{
rows = obj.rows;
cols = obj.cols;
mainArray = new int[rows*cols];
array = new int *[rows];
for (int i = 0; i < rows; i++)
array[i] = mainArray + (i*cols);
}
for (int i = 0; i < obj.rows; i++)
{
for (int j = 0; j < obj.cols; j++)
at(i, j) =obj.at(i,j);//PROBLEM
}
}
when im trying to assign at(i,j)=obj.at(i,j) i get this:
the object has type qualifiers that are not compatible with the member function
as far as i know, copy constructor is supposed to be passed by (const class& obj).
what should i do?
That's because your copy constructor take a const parameter, and your method Matrix::at is not const.
I suggest you to do two versions of your at method, one const and one not :
// Use for assignement
int& Matrix::at(int i, int j)
{
return array[i][j];
}
// Use for reading
int Matrix::at(int i, int j) const
{
return array[i][j];
}
Your compiler should know in which case call which one without your help, depending if you are trying to modify or just read your instance :
Matrix matrix(4, 4);
matrix.at(1, 2) = 42; // Assignement method called
int i = matrix.at(1, 2); // Read method called
Realize two versions of at function, one const and one non-const.
int& Matrix::at(int i, int j)
{
return array[i][j];
}
int Matrix::at(int i, int j) const
{
return array[i][j];
}
I have this code of a class representing a matrix:
class Matrix {
private:
int** M;
int n, m;
public:
Matrix(int _n, int _m, int v) {
n = _n;
m = _m;
M = new int*[n];
for (int i = 0; i < n; i++)
M[i] = new int[m];
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++)
M[i][j] = v;
}
}
int operator() (unsigned row, unsigned col) {
return this -> M[row][col];
}
void set(int i, int j, int v) {
M[i][j] = v;
}
};
I can not change the content of a cell when I use this class in the main function or within another class. I can only access/diplay a cell thanks to operator(), but I can not change its value unless I use the method set().
I would like to know if there is a why? Maybe using other methods or operators, to access and modify the content of a cell outside the class Matrix?
Just like this:
Matrix m(4,4,0);
m(2,2) = 10000; // ERROR!
and not
m.set(2,2,10000);
You have made int **M a private variable. The idea of a private variable is that you explicitly cannot change it outside of the class (see http://www.cplusplus.com/doc/tutorial/classes/). You can do one of two things:
Return a reference to the element as:
int &operator() (unsigned row, unsigned col)
{
return M[row][col];
}
Make int **M a public variable. This will allow you to access m.M[2][2] in main.cpp as normal.
I created a class called Matrix with a 2D array. I can run it with the constructor, copy constructor and destructor. When I introduce the unary negation operator, I get a run time error.
https://gist.github.com/anonymous/7823794
#ifndef MATRIX_H
#define MATRIX_H
class Matrix
{
public:
Matrix(int rSize=3, int cSize=3);
Matrix(const Matrix& m);
~Matrix();
bool setValue(int rSize, int cSize, int value);
bool getValue(int rVal, int cVal, int& value)const;
const Matrix operator- ();
private:
int rowSize;
int columnSize;
int** arr;
};
#endif
#include<iostream>
#include"Matrix.h"
using namespace std;
Matrix::Matrix(int rSize,int cSize)
{
columnSize = cSize;
rowSize = rSize;
arr = new int* [rowSize];
for(int i=0; i<rowSize; i++)
arr[i] = new int[columnSize];
for(int j=0; j<rowSize; j++)
{
for(int k=0; k<columnSize; k++)
arr[j][k] = 0;
}
}
Matrix::Matrix(const Matrix& m)
{
columnSize = m.columnSize;
rowSize = m.rowSize;
arr = new int* [rowSize];
for(int i=0; i<rowSize; i++)
{
arr[i] = new int [columnSize];
}
for(int i=0; i<rowSize; i++)
{
for(int j=0; j<columnSize; j++)
arr[i][j] = m.arr[i][j];
}
}
Matrix::~Matrix()
{
for(int i = 0; i < rowSize; ++i)
delete [] arr[i];
delete [] arr;
}
bool Matrix::setValue(int rVal, int cVal, int value)
{
if((rVal<0)||(cVal<0)||(rVal>rowSize-1)||(cVal>columnSize-1))
return false;
arr[rVal][cVal] = value;
return true;
}
bool Matrix::getValue(int rVal, int cVal, int& value)const
{
if((rVal<0)||(cVal<0)||(rVal>rowSize-1)||(cVal>columnSize-1))
return false;
value = arr[rVal][cVal];
return true;
}
const Matrix Matrix:: operator- ()
{
Matrix m(*this);
for (int i = 0; i< rowSize; i++)
{
for(int j=0; j<columnSize; j++)
m.arr[i][j] = (this->arr[i][j])* -1 ;
}
return m;
}
#include<iostream>
#include"Matrix.h"
using namespace std;
void main()
{
Matrix m(4, 5);
Matrix m2(m);
m2.setValue(1,2,12);
int x;
m2.getValue(1,2,x);
Matrix m3;
m3 = -m2;
}
Edit: Following #unwind and #interjay advice, I implemented the assignment operator first and returned a value, not a reference, for the negation operator and it works. Thank you all for your help
You don't have an assignment operator in your class, which will cause double deletion of the member pointer after an assignment (and you're assigning in the line m3 = -m2;).
You should obey the rule of three.
unwind is also correct that the negation operator should return by value: You should never return a reference to a local variable from a function as that leads to undefined behavior.
Declaring the operator to return const Matrix& and then returning a local variable is wrong. That's a dangling reference, surely?
See for reference this answer where the operator returns an actual new value, not a reference. This makes a lot more sense to me.