using operators with polymorphism in C++

Started by
21 comments, last by SiCrane 14 years ago
Quote:Original post by Antheus
Or, if a, b and c are all pointers to something, the following:
c = a + b;
is pointer arithmetic

No. Pointer arithmetic is one of the following:
pointer + ptrdiff_tpointer - ptrdiff_tpointer - pointer

Adding two pointers does not make any sense whatsoever.
Advertisement
Quote:Original post by daniel_i_l
But the problem is that if I'm working with pointers to the IVec class, then in order to use the operators I'll have to dereference all the pointers.


Then don't work with pointers. Work with references instead (i.e. just write the values, and have your overloads accept and return references where appropriate, following the usual conventions). References were actually added to the language more or less specifically to support operator overloading. They allow you to get 'virtual' behaviour for function calls (including operator overloads), too.

However, keep in mind that C++ does not have multiple dispatch built in. In 'x + y', only the exact derived type of x will matter for looking up the implementation, unless you explicitly re-dispatch, e.g.

IVec IVec::operator+(const IVec& rhs) {  return rhs.addedToBase(*this);}// Similarly for each derived type, naming a different helperIVec IVec::addedTo(const IVec& lhs) {  // protected virtual; does the work  // SImilarly for each derived type, accepting a parameter of that type}


But honestly, all of this is kind of moot, because operator overloads generally belong to simple mathematical types, and simple mathematical types have no reason for any polymorphic behaviour.
Quote:
You should consider making the member "impl" a shared pointer (std::tr1::shared_ptr) so you don't have to implement copy constructor and
assignment operator of MathVector.

That is dangerous. Leaving aside the fact that I wouldn't bother using any kind of runtime polymorphism for this, using a shared_ptr<> in the implementation means that Vector instances no longer act like simple mathmatical types, which can canuse unexpected and bizarre behaviour. I really wouldn't expect vector types to alias one another, its quite a violation of the principle of least surprise.

Something more appropriate for such use cases might be mr_edd's value_ptr<>.
Thanks for all the helpful replies. It seems like I shouldn't be using polymorphism for basic types. Maybe it'd be better to use templates? I could make a class with a signature like:
template<class Storage, class Math> Vector;
and then to create a vector you'd pass a "Storage" class that has getter and setter functions, and a "Math" class that uses the storage class to do the math.
Is that a good idea? Is there a better way to use templates?
Thanks
"We've all heard that a million monkeys banging on a million typewriters will eventually reproduce the entire works of Shakespeare. Now, thanks to the internet, we know this is not true." -- Professor Robert Silensky
Why do you need more than one kind of Vector at all? Or at worst, more than a few small sizes? Are you writing some kind of quantum-mechanics simulator or something? Nearly all practical applications don't have to worry about more than 3 dimensions of space, i.e. 3-element vectors or 4x4 matrices (due to homogeneous coordinates). Maybe you'd want a 4-element vector to represent a row or column of a 4x4 matrix, but that's about it.
Quote:Original post by Zahlman
Why do you need more than one kind of Vector at all? Or at worst, more than a few small sizes? Are you writing some kind of quantum-mechanics simulator or something? Nearly all practical applications don't have to worry about more than 3 dimensions of space, i.e. 3-element vectors or 4x4 matrices (due to homogeneous coordinates). Maybe you'd want a 4-element vector to represent a row or column of a 4x4 matrix, but that's about it.


I'm writing a rigid body simulator which solves large systems of equations.
In these equations, the system state and forces are represented by one long column vector. They have to be calculated together since they all influence each-other. In addition, my integrator also takes one column vector containing the states of all the bodies and one containing all of the derivatives.
"We've all heard that a million monkeys banging on a million typewriters will eventually reproduce the entire works of Shakespeare. Now, thanks to the internet, we know this is not true." -- Professor Robert Silensky
Quote:Original post by daniel_i_l

I'm writing a rigid body simulator which solves large systems of equations.
No physics or linear algebra ever needed or profited from use of polymorphism.

Quote:In these equations, the system state and forces are represented by one long column vector.
Which is what std::vector is used for.

Quote:They have to be calculated together since they all influence each-other. In addition, my integrator also takes one column vector containing the states of all the bodies and one containing all of the derivatives.
Which is also what std::vector is used for. The storage at least. Contents do not need to be polymorphic.

As a matter of fact, since the 1960s, all that was ever needed for solving these problems on computers was tape, or later an array.
linear algebra is based on the concept of polymorphism. vector spaces are written over fields, an extremely abstract concept. really all of linear algebra has been generalized to where all you have to do is have objects that satisfy a few requirements and you slip them in there.

abstract algebra
vector spaces in linear algebra.

for instance, you can use continuous real valued functions as your vectors. from a linear algebra point of view, they are the same.
Quote:Original post by Antheus
Which is what std::vector is used for.

But what if I want to apply various operators to my vectors? Don't I have to write a new class to do that?
"We've all heard that a million monkeys banging on a million typewriters will eventually reproduce the entire works of Shakespeare. Now, thanks to the internet, we know this is not true." -- Professor Robert Silensky

For a more advanced vector implementation using templates you can look at the eigen vector library http://eigen.tuxfamily.org/index.php?title=Main_Page

For large matrices the overhead for one virtual call is probably negelable. So if you need to be able to change storage and math at runtime, it is doable. But if you intend to implement operators using virtual methods it will add considerable overhead.

For a nice implementation I would do as imi suggests buy using a concrete wrapper which keeps track of a pointer.

If you need to do operators between different kinds of storage/math vectors then you need to look at the double dispatch pattern as Zahlman suggests.

If you dont need to be able to change implementation at runtime, then it will probably be better to manage without virtuals.

  typedef SparseMatrix EquationMatrix;  Vector vector(n);  EquationMatrix sparseEquations(n, n);    // ...  Vector resultVector = solve(sparseEquations, vector);


This topic is closed to new replies.

Advertisement