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
}
Related
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
I'm implementing a matrix class with some arithmetic. This is what I had as function for addition:
...
Matrix Matrix::operator+(const Matrix& other) const
{
Matrix out = *this;
out += scalar;
return out;
}
void Matrix::operator+=(const Matrix& other)
{
// Actually adding the numbers.
}
Just recently I found out that besides the copy constructor, I should also define a move constructor to avoid unnecessary copying of my matrix class. So I did that. And here's where it goes wrong. In the first line of my + operator, it will now move instead of copy and that causes off course a memory error.
So I revised to the following:
...
MatrixNT::MatrixNT(const MatrixNT&& other)
{
m_logger = LogWrapper::getLogger("MatrixNT");
m_rows = other.m_rows;
m_cols = other.m_cols;
m_data = other.m_data;
}
...
Matrix Matrix::operator+(const Matrix& other) const
{
Matrix out(*this);
out += scalar;
return out;
}
Is this the correct way of calling the copy constructor? It seems a bit odd, using the deference operator again. I can't find any examples on it.
I am thinking on how can i define a class of real matrices NxN with the operations Add (Subtract) and Multiply. I am looking for Efficient Memory Usage.
class Matrix {
private:
std::size_t _size_n;
double **_pMatrix;
public:
Matrix(const size_t n);
~Matrix();
double &operator()(size_t, const size_t);
double operator()(size_t, const size_t) const;
size_t size_n() const { return _size_n; }
};
std::ostream &operator<<(std::ostream &, const Matrix &);
Matrix operator+(const Matrix&, const Matrix&);
Matrix operator-(const Matrix&, const Matrix&);
Matrix operator*(const Matrix&, const Matrix&);
Yes you can have additional overloads
Matrix/*&&*/ operator+(const Matrix&, Matrix&&);
Matrix/*&&*/ operator+(Matrix&&, const Matrix&);
Matrix/*&&*/ operator+(Matrix&&, Matrix&&);
To reuse memory of one of the temporary.
They can all be implemented with Matrix& operator += (Matrix&, const Matrix&)
by changing the order as + is symmetrical. operator - would require dedicated code.
Another way to optimize memory is to use expression templates instead of computing directly the result.
It has its drawback about lifetime issue (especially with auto) though.
So I am trying to overload the operator* so both ways will work:
Myclass * a;
a * Myclass;
When I declare this function everything goes well:
Polynomial operator*(const double d);
But when I try doing it the other direction like this:
Polynomial operator*(Polynomial &, const double d)
I'm getting an error: "too many parameters for this operator function.
What am I doing wrong?
Thanks!
When you overload a binary operator as a member function, the class instance is always the left-hand operator and the argument to the function is the right hand, there's nothing you can do to change it. Not if you want to continue using member only functions.
But if you use a global non-member function you can easily have whichever order you want. For example
class Polynomial { ... };
// Function that allows poly * 12.34
Polynomial operator*(const Polynomial& lhs, const double rhs)
{
...
}
// Function which allows 12.34 * poly
Polynomial operator*(const double lhs, const Polynomial& rhs)
{
...
}
And if you don't want to reimplement the same code in both functions, and the operator is commutative (like multiplication and addition should be) then you can implement one of the function by calling the other:
Polynomial operator*(const Polynomial& lhs, const double rhs)
{
...
}
Polynomial operator*(const double lhs, const Polynomial& rhs)
{
return rhs * lhs; // Calls the operator function above
}
Of course, the operator taking the Polynomial object as left-hand side may of course be implemented as a member function.
On a related note, if you have implemented the operator as a member function, e.g.
class Polynomial
{
...
Polynomial operator*(const double rhs)
{
...
}
};
The the following code
Polynomial poly1(...);
Polynomial poly2 = poly * 12.34;
is equal to
Polynomial poly1(...);
Polynomial poly2 = poly.operator*(12.34);
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.