vector class

Started by
6 comments, last by Zahlman 18 years, 9 months ago
I would like to make a class for 3d vectors, and I would like it to feature the dot product and cross product operations. Ideally, I would like to do them using operator overloading, but it seems there's no real intuitive way of doing this. I suppose I could use the * operator for the cross product and the . operator for the dot product, but overloading the . like that could be really confusing. Has anyone found an intuitive way to support both dot and cross product with operators in C++? Mike C. http://www.coolgroups.com/
Mike C.http://www.coolgroups.com/zoomer/http://www.coolgroups.com/ez/
Advertisement
Can you even overload the . operator?

EDIT: Appears not.
.
Quote:Original post by mike74
Has anyone found an intuitive way to support both dot and cross product with operators in C++?


Overloading the * operator for cross product may get confusing, depending on how you implement your scalar multiplication. Consider this:
v1 = v2 * v3 * scalar

At first glance, there's 2 multiplications occuring. This can get more confusing as your equation's complexity rises. The alternatives would be a Vector3D::Cross( const Vector3D * ) method or a stand-alone function:
v1 = v2.Cross( &v3 ) * scalarv1 = Cross3D( &v2, &v3 ) * scalar

both of which are a little unruly. Intuitively, I'd use '*' for dot product and 'x' for cross product. Conceptually, since they're both symbolic of an equation, I'd use the stand alone function.

To answer your question, I haven't found an intuitive way to handle both of these equations using operators - maybe somebody else has.

:stylin:
:stylin: "Make games, not war.""...if you're doing this to learn then just study a modern C++ compiler's implementation." -snk_kid
All the people I trust say "use named member functions" on this one. A multiplication isn't obviously either dot or cross, '.' can't be overloaded, 'x' isn't even an operator, and anything else is just a ridiculous abuse. Besides, operations involving more than one (dot or cross) product in a row are rare, and with more than two are practically unheard of, so the normal syntax of member functions - or even of free functions - really isn't awkward here.
If you really want to have operators for these, you can overload '%' as dot product and '^' as cross-product. They're not very intuitive but keep operator priority.
I would prefer to use non-member functions for dot and cross product. Some people consider using member functions to be more intuitive; however, just as many consider using member functions to be counter intuitive as they may appear to be mutators of the object on the left hand side.

On the whole, I would recomment against overloading unrelated operators to provide the dot or cross product as operators already have a sense of built in meaning.

There are additional (bad) ways of handling this. One of my favorite bad methods goes like:
class Vector {  public:    Vector(float x = 0.0f, float y = 0.0f, float z = 0.0f)      : x_(x), y_(y), z_(z)    {}      public:    float x_;    float y_;    float z_;};template <typename Op>struct LtProxy {  LtProxy(const Vector & r) : ref_(r) {}  const Vector & ref_;};const struct DotT {} dot;LtProxy<DotT> operator<(const Vector & lhs, const DotT & rhs) {  return LtProxy<DotT>(lhs);}float operator>(const LtProxy<DotT> & lhs, const Vector & rhs) {  return ( (lhs.ref_.x_ * rhs.x_) +           (lhs.ref_.y_ * rhs.y_) +           (lhs.ref_.z_ * rhs.z_) );}const struct CrossT {} cross;LtProxy<CrossT> operator<(const Vector & lhs, const CrossT & rhs) {  return LtProxy<CrossT>(lhs);}Vector operator>(const LtProxy<CrossT> & lhs, const Vector & rhs) {  return Vector( (lhs.ref_.y_ * rhs.z_ - lhs.ref_.z_ * rhs.y_),                 (lhs.ref_.z_ * rhs.x_ - lhs.ref_.x_ * rhs.z_),                 (lhs.ref_.x_ * rhs.y_ - lhs.ref_.y_ * rhs.x_) );}int main(int, char **) {  Vector a(0, 1, 3);  Vector b(4, 2, 1);   float dot_product = a <dot> b;   std::cout << dot_product << std::endl;    Vector cross_product = a <cross> b;  std::cout << cross_product.x_ << std::endl;  std::cout << cross_product.y_ << std::endl;  std::cout << cross_product.z_ << std::endl;    return 0;}

This abuses the associativity of relational operators and operator overloading in general, is unmaintainable and can give operator precdence headaches, but it's fun.

Of course, I have a slightly twisted definition of fun.
Irrlicht engine, a 3d API that I'm currently working with, uses named member functions for both dot- and cross-product. I'd suggest, however, to use a non-member function (but within a namespace) or a static member function of Vector. Either of these methods would help you to stick with a good OO approach.
Vector3D cp = Vector3D::CrossProduct(vector1, vector2);float dp = Vector3D::DotProduct(vector1, vector2);
{[JohnE, Chief Architect and Senior Programmer, Twilight Dragon Media{[+++{GCC/MinGW}+++{Code::Blocks IDE}+++{wxWidgets Cross-Platform Native UI Framework}+++
Err, yes, I wasn't recalling quite properly when I wrote "named member functions". Good points, guys. :)

This topic is closed to new replies.

Advertisement