C++ operator overloading in a derived class - c++

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);

Related

Can't figure out why overloaded operator[] isn't getting called

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.

How to overload + to sum 2 objects that are matrix in c++?

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;
}

copy constructor error: the object has type qualifiers that are not compatible with the member function

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];
}

negation operator overloading in a class with a 2d array

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.

Class inheritance, copy constructor and set/get functions

I got the following class:
class Matrix{
private:
int rows;
int columns;
double* matrix;
public:
Matrix();
explicit Matrix(int N);
Matrix(int M, int N);
void setValue(int M, int N, double value);
double getValue(int M, int N);
bool isValid() const;
int getRows();
int getColumns();
~Matrix();
friend ostream& operator<<(ostream &out, Matrix&matrix1);
Matrix &operator=(const Matrix &m) {
if (rows * columns != m.rows * m.columns){
delete [] this->matrix;
this->matrix = new double[m.rows * m.columns];
}
rows = m.rows;
columns = m.columns;
for(int i = 0; i < rows; i++){
for(int j = 0; j < columns; j++){
this->matrix[i * columns + j] = m.matrix[i * columns + j];
}
}
return *this;
}
Matrix(const Matrix &rhs);
};
with these functions
#include <iostream>
#include "Matrix.h"
using namespace std;
//OPPGAVE 2
Matrix::Matrix(){
matrix = NULL;
}
Matrix::Matrix(int N){
matrix = new double[N * N];
rows = N;
columns = N;
for(int i = 0; i < N; i++){
for(int j = 0; j < N; j++){
if(i==j)
matrix[i * N + j] = 1;
else
matrix[i * N + j] = 0;
}
}
}
Matrix::Matrix(int M, int N){
matrix = new double[M * N];
rows = M;
columns = N;
for(int i = 0; i < M; i++){
for(int j = 0; j < N; j++)
matrix[i * N + j] = 0;
}
}
Matrix::~Matrix(){
delete [] matrix;
}
void Matrix::setValue(int M, int N, double value){
matrix[M * columns + N] = value;
}
double Matrix::getValue(int M, int N){
return matrix[M * columns + N];
}
bool Matrix::isValid() const{
if(matrix==NULL)
return false;
else
return true;
}
int Matrix::getRows(){
return rows;
}
int Matrix::getColumns(){
return columns;
}
ostream& operator<<(ostream &out, Matrix&matrix1){
if(matrix1.isValid())
for(int i = 0; i < matrix1.getRows(); i++){
for(int j = 0; j < matrix1.getColumns(); j++)
out << matrix1.getValue(i,j) << "\t";
out << endl;
}
else
out << "Matrisen er ikke gyldig." << endl;
return out;
}
Matrix::Matrix(const Matrix &rhs) : rows(rhs.rows),
columns(rhs.columns),
matrix(new double[rows * columns]) {
for (int i = 0; i < rows; i++) {
for (int j = 0; j < columns; j++) {
this->matrix[i * columns + j] = rhs.matrix[i * columns + j];
}
}
}
The exercise says:
a) Create a class Vector that inherits the MxN Matrix.
We want to use the Vector class as an interface to an Mx1 dimensional matrix with some
extra functionality.
b) Implement the following constructors for the Vector class.
• Vector()
Default constructor, should initialize the underlying matrix into the invalid state.
• explicit Vector(unsigned int N)
Should construct the underlying Mx1 Matrix, initialized as a zero-matrix. (The explicit keyword is not in the syllabus, but it should be used here.)
• Vector(const Matrix & other);
Copy-constructor from Matrix. Should assign a matrix to *this if and only if the matrix has dimensions Nx1, otherwise the resulting *this should be set to invalid. Hint: Reuse operator= from the Matrix-class.
This is what I've got so far:
#include "Matrix.h"
class Vector : public Matrix{
public:
Vector();
explicit Vector(int N);
Vector(const Matrix & other);
};
and
using namespace std;
#include <iostream>
#include "Vector.h"
Vector::Vector()
:Matrix(){ }
Vector::Vector(int N)
:Matrix(N,1){ }
How am I supposed to reuse the operator= from Matrix? If I try to copy it from the Matrix class into the Vector class, it says that rows, columns etc is inaccessible. How do I access these?
Is it possible to write a copy constructor for the Vector class more or less the same as the copy constructor for the Matrix class? They are both arrays, so I guess it should work?
Will the operators I overloaded for Matrix (not included here) automaticly be used if I multiply a Matrix with a Vector, or do I also need to include these somehow in the Vector class? (They were written outside the Matrix class in the Matrix.cpp-file.)
Next Im going to write set and get functions for the Vector class.
Is it possible to write these functions on this form?:
void Vector::setValue(int i, double value) {
Matrix::setValue(i, 1, value);
}
Help and tips are greatly appreciated!
What follows is hideous kludgery to satisfy an incompetent professor. Don't do this in the real world.
First, the misnamed "copy" constructor. If we weren't worried about the dimensions, we could do this (shudder):
Vector(const Matrix & other)
{
*this = other;
}
But we must check the dimensions first. We could do it this way:
Vector(const Matrix & other)
{
if(other.getColumns()==1)
*this = other;
}
But some chucklehead neglected to make getColumns() const, so this results in a compiler error. We could do something truly drastic, const cast:
Vector(const Matrix & other)
{
Matrix *p = const_cast<Matrix *>(&other);
if(p->getColumns()==1)
*this = other;
}
Or just something facepalmingly awful:
Vector(const Matrix & other)
{
Matrix M(other); // notice that this is not const
if(M.getColumns()==1)
*this = other;
}
Do you need help with the isValid stuff?
You are on the right track for the sets and gets. You can call operators with member function like syntax Class::operator*(args). Implementing the vector assignment would look something like this:
Vector & Vector::operator=(const Vector &v){
Matrix::operator=(v);
return *this;
}
You will want your Vector constructors to be declared public. I am thinking because you are using inheritance the compiler will generate correct copy constructors and assignment operators for the Vector class. You should write tests to verify this assumption.