Pantelis Sopasakis
Pantelis Sopasakis

Reputation: 1902

Operator+ to add instances of different classes

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

Answers (3)

JRR
JRR

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

user2249683
user2249683

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

John P
John P

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

Related Questions