c++ matrix class: overloading assignment operator - c++

I'm having some trouble implementing an assignment operator for a matrix class. It seems that the compiler doesn't want to recognize my overloaded assignment operator (I think?) and I'm not sure why. I know there are some internet articles on the various issues with implementing matrix classes in c++ (which have helped me get this far) but this time I can't seem to parallel my current predicament with any other help already out there. Anyway, I would greatly appreciate it if someone could help explain what I'm doing wrong. Thanks!
Here are my error messages:
In file included from Matrix.cpp:10:
./Matrix.h:20:25: error: no function named 'operator=' with type 'Matrix &(const Matrix &)'
was found in the specified scope
friend Matrix& Matrix::operator=(const Matrix& m);
^
Matrix.cpp:79:17: error: definition of implicitly declared copy assignment operator
Matrix& Matrix::operator=(const Matrix& m){ //m1 = m2
^
Matrix.cpp:89:13: error: expression is not assignable
&p[x][y] = m.Element(x,y);
~~~~~~~~ ^
3 errors generated.
Here is my assignment operator code in my .cpp file:
Matrix& Matrix::operator=(const Matrix& m){ //m1 = m2
if (&m == this){
return *this;
}
else if((Matrix::GetSizeX() != m.GetSizeX()) || (Matrix::GetSizeY()) != m.GetSizeY()){
throw "Assignment Error: Matrices must have the same dimensions.";
}
for (int x = 0; x < m.GetSizeX(); x++)
{
for (int y = 0; y < m.GetSizeY(); y++){
&p[x][y] = m.Element(x,y);
}
}
return *this;
here is my matrix header file:
class Matrix
{
public:
Matrix(int sizeX, int sizeY);
Matrix(const Matrix &m);
~Matrix();
int GetSizeX() const { return dx; }
int GetSizeY() const { return dy; }
long &Element(int x, int y) const ; // return reference to an element
void Print() const;
friend std::ostream &operator<<(std::ostream &out, Matrix m);
friend Matrix& Matrix::operator=(const Matrix& m);
long operator()(int i, int j);
friend Matrix operator*(const int factor, Matrix m); //factor*matrix
friend Matrix operator*(Matrix m, const int factor); //matrix*factor
friend Matrix operator*(Matrix m1, Matrix m2); //matrix*matrix
friend Matrix operator+(Matrix m1, Matrix m2);

Your assignment operator should be a member function, not a friend. Your other operators should take parameters as const Matrix &, otherwise you'll make a copy of the Matrix objects used by the operator.

You're taking the address of the element:
&p[x][y] = m.Element(x,y);
when you want to assign to it, like this:
p[x][y] = m.Element(x,y);

friend Matrix& Matrix::operator=(const Matrix& m);
This above part makes little sense since operator= must be defined as a member function within the class.
Actually I think your life would be a lot easier if you avoided the need for friends here (or at least so many of them). A self-sufficient public interface for a matrix should allow you to implement all the desired operators, whether or not they're members of the class.
Perhaps the first thing you should seek is that self-sufficient public interface so that you don't actually need something like a matrix multiplication operator to be a friend, since otherwise the likely temptation would be to make every operation involving matrices require access to the matrix internals.

Related

Get private element outside the class

First of all it's an exercise given to me so i can't change things and have to work with it.
I have a 2d vector aka a matrix. My header file looks like this
#include <vector>
#include <iostream>
using namespace std;
class Matrix{
private:
vector<vector<double>> 2d;
public:
explicit Matrix(unsigned int sizeY=0,unsigned int sizeX=0,double value= 0.0);
~Matrix() = default;
Matrix(const Matrix &other);
Matrix(Matrix &&other) = default;
Matrix& operator=(const Matrix &other);
Matrix& operator=(Matrix &&other) = default;
//other + - operators
//INDEX
vector<double>& at(unsigned int i);
const vector<double>& at(unsigned int i)const;
const vector<double>& operator[] (double m) const;
vector<double>& operator[] (double m);
};
Matrix operator+(const Matrix& d1, const Matrix& d2);
Matrix operator-(const Matrix& d1, const Matrix& d2);
ostream& operator<<(ostream &o, const Matrix& v);
istream& operator>>(istream &i, Matrix& v);
So now I implemented everything except the << and >> operator.
Now the question if i want to go through the 2d vec matrix is there another way to get the "depth"
outside the Matrix class except writing a getter ?
If the Matrix is N X M e.g. 4x4 i can get the 2nd 4 the "width" with something like 2d[0].size() but i cant figure out how I can get the "depth" otherwise then use a getter.
Also i cant change 2d to public or use templates.
I tried for around 2-3 hours myself and couldnt find any solution and maybe its not possible under the given conditions.
2d[0].size() is giving you the length of the first vector stored in 2d. To get the length of 2d you can just call the same directly on 2d.
2d.size() = length of 2d
2d[0].size() = length of first vector stored in 2d

C++ overloading operators for matrix structure

I am trying to make matrix structure with overloading operators '+' and '='.
Matrix structure:
struct Matrix{
int rows;
int cols;
std::vector<int> data;
Matrix(int rows, int cols, int val); //creates matrix row*col and fills every position with val
Matrix(const Matrix &m); //copy constructor
Matrix(int rowcol = 0); //creates matrix rowcol*rowcol filled with zeros
Matrix & operator=(const Matrix &m);
void printMatrix(); //prints the matrix
...
};
Operators:
Matrix & Matrix::operator=(const Matrix &m) //assings matrix m to the new matrix
{
}
Matrix operator+(const Matrix &a, const Matrix &b) //sums two matrices
{
//I know how to make the algorithm for summing two matrices, however i don´t know how
//to return the result into existing matrix
}
And main function:
int main(){
Matrix A(3,3,1);
Matrix B(3,3,2);
Matrix C(3,3,0);
C = A + B;
C.printMatrix();
...
return 0;
}
I don´t know how to make it work. I tried something like this for the '=' operator:
Matrix & Matrix::operator=(const Matrix &m)
{
static matrix d(m); //using copy constructor
return d;
}
but it didn´t work. It created new matrix with dimensions 0x0. Any advice on how to implement it?
A working way to implement that operator= would be as follows:
Matrix& Matrix::operator=(const Matrix &m)
{
this->rows = m.rows;
this->cols = m.cols;
this->data = m.data;
return *this;
}
I won't approach the algorithm needed for operator+, but the surrounding machinery is also surprisingly simple:
Matrix operator+(const Matrix &a, const Matrix &b) //sums two matrices
{
Matrix result(<num of rows>, <num of cols>, 0);
// do things with result here, using your algorithm, a, and b
// e.g. result.data[?] = a.data[?] ? b.data[?]
return result;
}
To make this easier, since your data is one-dimensional (good! this is efficient!), you may want to implement an accessor that takes x and y dimensions and returns an index into data. For example:
int& Matrix::val(const int x, const int y)
{
assert(x < cols);
assert(y < rows);
return data[x + y*cols];
}
The result of this may be both read and written, like this:
result.val(x1, y1) = a.val(x2, y2) + b.val(x3, y3);
Where those co-ordinates and the + are just things I made up, and should come from your algorithm.
If you also want an operator+=, to affect an existing matrix, then:
Matrix& Matrix::operator+(const Matrix &b) //sums two matrices
{
// do things with your object here, using your algorithm and b
return *this;
}
Where I return *this for the member operators, that's not strictly necessary, though it is conventional, and it allows for easy chaining of operations (if you're into that kind of thing). You can find more information on operator overloading in your book.

Error happens when use friend function to manipulate private variables in template class in C++

I am writing a matrix operation library recently.And I want to overload operator s in my program, but Error happened when I use friend function to access private variables in the template class I was defined. (And it reports error only when I overload the operator '+', and the overload function of operation '-' doesn't report error.)
the template class I defined is below:
template<class T>
class Matrix
{
int col;
int row;
T *matrix;
public:
Matrix(T *m, int row1, int col1):matrix(m), row(row1), col(col1){}
Matrix(int row1, int col1):row(row1), col(col1)
{
matrix = new T[row*col];
cout<<"Have set the shape of the matrix, but should use create() to initialize the matrix!"<<endl;
}
Matrix(){}
~Matrix(){}
void show();
UINT create(T *m);
UINT zeros(int size);
UINT eye(int size);
// the overload function statement
friend Matrix operator+(const Matrix &a, const Matrix &b);
friend Matrix operator-(const Matrix &a, const Matrix &b);
Matrix matrix_T(); // transpose the matrix
Matrix matrix_Inv(); // calculate matrix's inverse
Matrix matrix_Adjoint(); // calculate the adjoint matrix
};
And the defination of this two overload functions are below:
// report error: can't access private member declared in class
template<class T>
Matrix<T> operator +(const Matrix<T> &m1, const Matrix<T> &m2)
{
if (m1.col!=m2.col || m1.row!=m2.row)
{
cout<<"These two matrices can't be plused!"<<endl;
exit(0);
}
T *tmp = new T[m1.col*m1.row];
for (int i=0; i<m1.row; i++)
{
for (int j=0; j<m1.col; j++)
{
tmp[i*m1.col+j] = m1.matrix[i*m1.col+j] + m2.matrix[i*m1.col+j];
}
}
return Matrix<T>(tmp, m1.row, m1.col);
}
// this defination didn't report error
// and if I only run this code, there is nothing wrong
template<class T>
Matrix<T> operator -(const Matrix<T> &m1, const Matrix<T> &m2)
{
if (m1.col!=m2.col || m1.row!=m2.row)
{
cout<<"These two matrices can't be plused!"<<endl;
exit(0);
}
T *tmp = new T[m1.col*m1.row];
for (int i=0; i<m1.row; i++)
{
for (int j=0; j<m1.col; j++)
{
tmp[i*m1.col+j] = m1.matrix[i*m1.col+j] - m2.matrix[i*m1.col+j];
}
}
return Matrix<T>(tmp, m1.row, m1.col);
}
I've tested these two pieces of code seperately, the overload of operator '-' can be compiled correctly, but operator '+' can't.
The error imformations are below:
f:\program\c++\matrixoperate\matrixdefine.h(134) : error C2248: 'col' : cannot access private member declared in class 'Matrix<int>'
f:\program\c++\matrixoperate\matrixdefine.h(6) : see declaration of 'col'
f:\program\c++\matrixoperate\demo.cpp(14) : see reference to function template instantiation 'class Matrix<int> __cdecl operator +(const class Matrix<int> &,const class Matrix<int> &)' being compiled
f:\program\c++\matrixoperate\matrixdefine.h(134) : error C2248: 'col' : cannot access private member declared in class 'Matrix<int>'
f:\program\c++\matrixoperate\matrixdefine.h(6) : see declaration of 'col'
And the IDE I use is VC++6.0.
friend Matrix operator+(const Matrix &a, const Matrix &b); is not a template. It is a non template friend function of a template class.
template<class T>Matrix<T> operator +(const Matrix<T> &m1, const Matrix<T> &m2) is a template. They are not the same function, as one is a template the other is not.
The easiest way to fix this is to put the body inline in the template class definition.
The second easiest way is to forward from operator+ to some static method, or some named function template. Forward declare it before the template class definition, friend it in the template class definition, implement it afterwarss.
(You actually want operator+ to be a non-template friend of a template class, as that makes it play much nicer with conversions.)
So do https://stackoverflow.com/a/13464246/1774667 but for a named function, not an operator. Call it add.
Then friend Matrix operator+(const Matrix &a, const Matrix &b){ return add(a,b); } which gives you the non-template friend operator of template class magic.

Implementing inner operator for derived class

Assume I have a general Matrix class, for which I have already implemented the operator * which performs the usual matrix multiplication.
Such an operator has the following signature :
Matrix operator*(const Matrix & ) const;
I now wish to implement another * operator for an inherited class Matrix3 that represents 3x3 matrices.
It would have the following signature :
Matrix3 operator*(const Matrix3 &) const;
I am looking for the proper way of implementing this operator in order to re-use the code already written for the base class, and to minimize cost (i.e. copying).
This should work just fine:
// Either return base class
Matrix operator*(const Matrix3& other) const
{
return Matrix::operator*(other);
}
// Or construct from a Matrix
Matrix3 operator*(const Matrix3& other) const
{
return Matrix3(Matrix::operator*(other));
}
// Either construct the Matrix data in the Matrix3
Matrix3(const Matrix& other)
{
// Initialize Matrix specifics
// Initialize Matrix3 specifics
}
// Or pass the Matrix to it's base class so it can take care of the copy
Matrix3(const Matrix& other) : Matrix(other)
{
// Initialize Matrix3 specifics
}

How to do operator overloading

How do I write a program to overload the + operator so that it can add two matrices?
From http://www.parashift.com/c++-faq-lite/operator-overloading.html#faq-13.1
The idea is to call functions using
the syntax of C++ operators. Such
functions can be defined to accept
parameters of user-defined types,
giving the operators user-defined
meaning. For example:
Matrix add(const Matrix& x, const Matrix& y);
Matrix operator+(const Matrix& x, const Matrix& y);
Matrix use_add(const Matrix& a, const Matrix& b, const Matrix& c)
{
return add(a,add(b,c));
}
Matrix use_plus(const Matrix& a, const Matrix& b, const Matrix& c)
{
return a + b + c;
}
Also, this forum thread from lansinwd discusses this in detail
The idiomatic way to overload operators is the following.
struct M {
...
M & operator+=(M const& rhs) {
loop * 2 to increment
return this;
}
};
M operator+(M lhs, M const& rhs) {
return lhs += rhs;
}
But have a look at Blitz++, newmat and boost solutions that eliminate temporary objects thanks to Expression Templates -- C++0x's rvalue references will simplify ET solution.
NB: You will prefer to implement op*= in terms of op* instead of the other way around.