Problem statement: Let Matrix be a base class which is subclassed by DenseMatrix and SparseMatrix (and possibly others). What I would like to achieve is the following:
Matrix *A = new DenseMatrix();
Matrix *B = new SparseMatrix();
Matrix C = (*A) + (*B); // dense + sparse
Matrix D = (*A) + (*A); // dense + dense
Matrix E = (*B) + (*B); // sparse + sparse
Even better, I would like to have the following:
DenseMatrix C = (*A) + (*B);
DenseMatrix D = (*A) + (*A);
SparseMatrix E = (*B) + (*B);
Now, when adding a DenseMatrix with a SparseMatrix having declared both as Matrix implies that there must be an operator+ definition in Matrix.
I have already read this answer which makes use of an interface AddEnabled<Foo>, but doesn't seem to be a good solution when (almost) any possible combination of summands. I could possibly define in DenseMatrix the following functions:
friend DenseMatrix operator+ (DenseMatrix const& left, DenseMatrix const& right);
But then again it will be impossible to add two instances of DenseMatrix declared as Matrix (i.e., Matrix *A = new DenseMatrix();).
From various similar questions and answers I suspect that the pimpl idiom could be relevant, but I don't see how.
Note: I'm coding in C++98, not C++11.
Update: As Dieter Lücking suggested in his answer an opeator+ needs to be introduced in the base class. This makes sense, but the problem is that Matrix, being abstract, does not allow methods which return abstract types. However, it is possible to return a pointer or a reference to Matrix; this way we would have a definition like:
Matrix& operator+(const Matrix& right) const;
To an extent this would work, but users of my code would expect a + to return a Matrix instead of a reference to one.
You may give the base class a state indicating the matrix layout - having that, dispatch matrix operations (on the base class) accordingly. Keep the special matrices classes for construction, but they will elide to the base matrix after applying an operation.
Example:
Matrix = IdentityMatrix operation DiagonalMatrix
This would elide the argument types and result in a matrix having a state 'Diagonal'
You might need to declare your Matrix::operator+ as virtual if you re-define it in your sub-classes and you initialize them as
Matrix *A = new DenseMatrix();
Also why is operator+ not a member of DenseMatrix? What I mean is
DenseMatrix DenseMatrix::operator+ (DenseMatrix const& right) const;
instead of
friend DenseMatrix operator+ (DenseMatrix const& left, DenseMatrix const& right);
Are you sure you need to re-overload operator+ in you derived classes again?
Can't you just inherit operator+ from your base class Matrix?
Edit:
If your base class does not have an operator+, but your derived ones do, you still need to declare (but not define) one as virtual in the base class, otherwise the derived classes cannot override it when they are pointed to by a Matrix* and not a DenseMatrix*.
Not sure why you want multiple + operators. Matrix addition is the same, no matter what the matrix representation:
1. Ensure the matrices being added have the same dimensions.
2. Add corresponding entries from the input matrices to produce the values in the output matrix.
These operations will be done in the base class operator +.
Then all you need is to implement getDimensions() in each subclass and, if they are equal, perform:
result.put(x, y, inputA.get(x, y) + inputB.get(x, y));
for each entry in the matrices.
Related
In my program, I use many arma::uvecs, and check equality between them like this
#include <armadillo>
using Vec = typename arma::uvec;
Vec v1({0, 0});
Vec v2({0, 1});
bool are_equal = arma::all(v1 == v2);
as I couldn't find any better equality operator in the Armadillo docs. Now that works perfectly fine, but to save some space, and as an exercise in subclassing and operator overloading, I want to define the equality sign directly between the vectors like this:
class Vec : public arma::uvec {
friend bool operator==(const Collapsed& lhs, const Collapsed& rhs) {
return arma::all(lhs == rhs);
}
};
But sadly, I can't get it to work like that. I'm grateful about any hints!
Operator overloads do not need to be part of a class. I would suggest implementing your comparison operator as a free function like this:
bool operator==(const arma::uvec& lhs, const arma::uvec& rhs) {
return arma::all(lhs == rhs);
}
Regarding the friend in your question: As a quick summary, it provides the function that is befriended access to private and protected members of the class where the friend declaration is located. It it is not used to implement functions.
You can read more about it on cppreference or on this SO question
EDIT
Since the above only works if operator== is not already defined, here is a version that overrides it's implementation for a custom subclass:
class Vec : public arma::uvec
{
public:
bool operator==(const Vec& other)
{
// depending on wether arma implemets operator== as member or free function
// return arma::all(this->arma::uvec::operator==(other));
return arma::all(arma::operator==(*this, other));
}
};
Problem is library itself:
Armadillo: C++ library for linear algebra & scientific computing
operators: + − * % / == != <= >= < > && ||
Overloaded operators for Mat, Col, Row and Cube classes
Operations:
+ addition of two objects
− subtraction of one object from another or negation of an object
* matrix multiplication of two objects; not applicable to the Cube class unless multiplying by a scalar
% element-wise multiplication of two objects (Schur product)
/ element-wise division of an object by another object or a scalar
== element-wise equality evaluation of two objects; generates a matrix/cube of type umat/ucube
!= element-wise non-equality evaluation of two objects; generates a matrix/cube of type umat/ucube
and uvec is:
uvec = ucolvec = Col<uword>
so operator== is already there and its functionality is strange/unexpected.
My recommendation is: do not fight with a library. Do not try provide own operator. Just provide a named function areEqual.
Defining a class just to provide own equal operator is not a best choice and if doing that then IMO it is better to use composition not inheritance (depending on requirement it will be more boiler plate code in class itself, but it will be easier to avoid unexpected behaviors).
I'm looking for advice as to how to proceed with this class hierarchy I'm building in C++.
Base class is Matrix:
class Matrix
{
protected:
int rows;
int columns;
double* values;
public:
\\lots of stuff goes here. bla di bla di bla.
virtual Matrix operator+(const Matrix& addend) const;
\\etc.
}
Squarematrix is inherited from Matrix
class Squarematrix : public Matrix
{
public:
Squarematrix operator+(const Squarematrix& addend) const;
}
Operator+ returns a matrix or a squarematrix respectively. Since operator+ is a virtual function this wont compile, as it must have the same return type in all classes.
So what are my options?
I could use an ordinary function instead of virtual. This is a bit annoying, but wouldn't cause a problem under most circumstances.
I could return a matrix in all cases. This would basically make my squarematrix class a right pain in the *** to use, as I would have to constantly downcast from matrix to squarematrix.
I could return a reference to a squarematrix. Then the matrix would have to be stored on the heap and there's no way to make sure its deleted safely. Especially if I do something like this:
squarematrix a=b+(c+d);
(c+d) will be stored on the heap and have no pointer to it so will be leaked.
Is there any way to keep virtual functions and still have different return types?
What would you advise in this situation?
Thanks for your help. Looking forward to hearing from you.
I would recommend:
Remove Squarematrix.
Add a constructor to Matrix to construct a square matrix.
If the knowledge of whether a matrix is square matrix is helpful for your application, add a member function in Matrix to answer that query.
class Matrix
{
public:
Matrix(int r); // Construct a square matrix.
Matrix(int r, int c); // Construct a rectangular matrix.
bool isSquareMatrix() const { return (rows == columns); }
Matrix operator+(const Matrix& addend) const;
private:
int rows;
int columns;
double* values;
}
This is known as return type covariance (https://en.wikipedia.org/wiki/Covariant_return_type).
It was not supported by old compilers, but is supported by many now. For example my code compiles fine in Visual Studio 2017. Here is an article on its use and limitations in c++: https://aycchen.wordpress.com/2009/08/17/covariant-return-type-in-cpp/.
It is not supported in C# yet, but is being considered for a future version. See https://github.com/dotnet/csharplang/issues/49.
It is also supported by newer versions of Java. See https://blogs.oracle.com/sundararajan/covariant-return-types-in-java.
Other than implementation issues, as far as I know there is no reason for it not to be added to a polymorphic language. I don't believe it can cause errors, although due to an imperfect implementation in Java it can cause bugs-see https://dzone.com/articles/covariant-return-type-abyssal.
I have a coursework that involves implementing two classes, one to store Matrix objects and a child of this for SquareMatrix objects. We have to implement member functions to be able to solve an equation of the form Ax = b, with A being the matrix, x being the vector we want to find and b being a known vector.
I've implemented this in the case of a SquareMatrix since it is not too hard to do with Gaussian elimination. The method that the coursework says we should use to solve the case with a non-square matrix is to solve A'Ax = A'b with ' meaning transpose. A'A is now a square matrix so this can be solved using Gaussian elimination also.
What I wanted to know was whether it is a valid thing to do to create a SquareMatrix object in the Matrix solve function and then use the SquareMatrix member solve to solve the system. So for instance if in SquareMatrix I have
Matrix SquareMatrix::solve(Matrix& b){
//stuff that solves (*this) * x = b for x and returns x
}
Could I then in Matrix.cpp have
Matrix Matrix::solve(Matrix& b){
//make the matrix into a square
SquareMatrix AtransposeA = (this->transpose())*(*this);
//update rhs of equation accordingly
Matrix Atransposeb = (this->transpose()) * b;
//Call SquareMatrix solve to solve the problem.
Matrix x = AtransposeA.solve(Atransposeb);
return x;
}
So I'm making the matrix square by multiplying by its transpose and then calling the SquareMatrix solve function. I'm relatively new to C++ and haven't 100% gotten my head around inheritance so I'm not sure if this a valid, or sensible thing to do.
I'm not sure if this a valid, or sensible thing to do.
It is valid to use a derived class, to implement a function of parent class in some cases.
Whether it makes sense for SquareMatrix to be derived from Matrix is another consideration. To know the answer to that question, you'll need to consider your design, and outline all class invariants and member function pre- and post-conditions of Matrix and then consider whether SquareMatrix can satisfy them all.
I want to implement a representation of matrices. for that I have two types of matrices - regular and sparse, which differ in their implementation - one holds a vector, and the second a map of indices and value, both inherit from Matrix class.
For that, I'm using the strategy pattern, where I create the base abstract class Matrix, two classes that inherit from Matrix - RegMatrix and SparseMatrix, and MyMatrix that holds a pointer to a Matrix.
I want to implement the + operator, which operates on Matrix and receives another Matrix. but when I implement the + operator, I might receive as parameter sparse/regular matrix.
so I have 2 questions:
The only hint I have is to create an iterator of type "matrix", and implement the iterator for each type of matrix (regular and sparse).
how can I do such a thing?
Let's say I implemented an iterator for both types of "matrix". how can I use the different iterators, in case I have to add two different types of matrices? do I have to implement all 4 different cases?
The operator+ looks like:
Matrix& operator+(const Matrix& other)
{
.....
}
Prefer not to implement the functionality in the base class.
Implement the functionality in each of the child classes. This will allow for use of optimal algorithms.
Or you could declare getters and setters as abstract in the Base class and use them in your base class implementation:
struct Matrix_Base
{
virtual int get_value(unsigned int row, unsigned int column) = 0;
virtual void set_value(int value, unsigned int row, unsigned int column) = 0;
Matrix_Base operator+(const Matrix_Base& other)
{
// perform addition
int sum = get_value(row, column) + other.get_value(column, row);
set_value(sum, row, column);
//...
}
};
Remember, when passing a Matrix, the receiving function can only use common functions (interface) of the Matrix. For specifics, functions will have to use specialized (descendants) in the parameter lists.
You may implement + operator only for RegMatrix and 2 conversion operators:
1. From RegMatrix to SparseMatrix
2. From SparseMatrix to RegMatrix
What are performance requirements?
I can operate class+class (for example I can do date+date), but can anyone explain how can I do class+class+class please? C++ does not let me define an operator with 2 parameters.
That's because there is no such operator in general.
a + b + c is (a + b) + c. First a + b, then the results
of that added to c.
EDIT:
If the objects in question are extremely big, so that creating
the temporaries in an expression like a + b + c is too
expensive, you can google for template expressions; the basic
idea is that operator+ doesn't do anything but return an
expression node, which can be evaluated later, as part of the
full expression.
By making them friends of the class, you would make sure they are binary operators, and define them separately, like so:
class someclass
{
int a;
public:
someclass();
...
friend someclass operator+(const someclass & lhs, const someclass & rhs);
};
someclass operator+(const someclass &lhs, const someclass &rhs)
{
someclass a = lhs;
a.a = a.a + rhs.a;
return a;
}
you will, of course need to define a copy constructor (someclass(const someclass & old);) and the other functions of the class, but this method has always worked for me, and it was how I was taught in college.
There are two ways you can approach this. The normal way with operators is, you just create a normal two operand operator, and then chain the calls together. For example a + b + c + d => operator+(operator+(operator+(a + b), c), d).
Alternately, create your own named function or member that provides a multi-parameter version, using the name to accurately describe what it does.
I suggest reading http://www.cs.rit.edu/~mjh/docs/c++-faq/operator-overloading.html
To the best of my understanding you do not need 2 parameters here. Your overload needs to return an object which the result of your operation. In this case your example class+class+class can actually be written as class+(class+class) so that (class+class) is processed first and then the result of that is added to the third class.
You are allowed to use arithmetic operators with two parameters. For example:
//References are used here as arguments.
Cents operator+(const Cents &c1, const Cents &c2)
{
// use the Cents constructor and operator+(int, int)
return Cents(c1.m_nCents + c2.m_nCents);
}
(Source: http://www.learncpp.com/cpp-tutorial/92-overloading-the-arithmetic-operators/)
Note: you need to declare the operator "function" as friend in class definition if you need to use private members of your class in it.
If you then return a class type same with those given as arguments (objects or references of them as here), you can do class + class + class..., assuming that each operator+ call is between 2 arguments, and the result is added to the third one invoking again the operator+ "function" etc.