Reputation: 1902
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.
Upvotes: 1
Views: 102
Reputation: 66
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.
Upvotes: 0
Reputation:
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'
Upvotes: 1
Reputation: 1
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*
.
Upvotes: 0