overloading unary operators issue

Started by
7 comments, last by SiCrane 12 years, 10 months ago
trying to make a vector class for collision detection in c++.
The problem is that when i hold references of the vectors in pointers...i can no longer overload unary operators to simplify the code.

for Example , lets say i wanted to Add vector A and B this is what i would write:



#include <iostream>

using namespace std;
class Vector2D{
public:
double X;
double Y;
Vector2D(double IX, double IY){
X = IX;
Y = IY;
}
void AddVector2D(Vector2D * B){
this->X = this->X + B->X;
this->Y = this->Y + B->Y;
}
Vector2D * operator + (Vector2D * B){
AddVector2D(B);
return this;
}
void Disp(){
cout <<this-> X << "," ;
cout <<this-> Y <<endl;
}
};
int main(){
Vector2D * A = new Vector2D(1,1);
Vector2D * B = new Vector2D(1,1);
Vector2D * C = A + B;
// 'A+B' should return a modified A vector
// error: incalid operands of types 'vector2D*' and 'vector2D*' to binary operator+
return 0;
}



But this doesn't compile. Whats going on? Why wont this compile?
Everything seems to be in order (to me..).
Advertisement
Well that just looks nasty. I would do my best to remove the pointers (pass by reference). You could try dereferencing A first then adding it because as it is right now your just adding two pointers.

Vector2D *C = *A + B;

You could also try making a "free" + operator outside of the class that takes two pointers to Vector2D objects. No idea if that would work but:

Vector2D* operator+(Vector2D *A, Vector2D *B)
{
A->AddVector2D(B);
return A;
}


What your doing appears very bizzare and awkward to do, what are you trying to do exactly? It looks like you should be overloading the += operator, your using the + operator in a way thats confusing. If your adding two vectors you shouldn't be modifying one. No reason why you can't but its just confusing.

Vector2D& operator+=(const &rhs)
{
X += rhs.X;
Y += rhs.Y;
return *this;
}

Vector2D * A = new Vector2D(1,1);
Vector2D * B = new Vector2D(1,1);
Vector2D &C = (*A) += *B; // Need to dereference them since they are pointers

Interested in Fractals? Check out my App, Fractal Scout, free on the Google Play store.


You could also try making a "free" + operator outside of the class that takes two pointers to Vector2D objects. No idea if that would work but:

It won't. Overloaded operators (aside from new and delete) need to have at least one parameter of class type, reference to class type, enum type or reference to enum type.

Well that just looks nasty. I would do my best to remove the pointers (pass by reference). You could try dereferencing A first then adding it because as it is right now your just adding two pointers.

Vector2D *C = *A + B;

You could also try making a "free" + operator outside of the class that takes two pointers to Vector2D objects. No idea if that would work but:

Vector2D* operator+(Vector2D *A, Vector2D *B)
{
A->AddVector2D(B);
return A;
}


What your doing appears very bizzare and awkward to do, what are you trying to do exactly? It looks like you should be overloading the += operator, your using the + operator in a way thats confusing. If your adding two vectors you shouldn't be modifying one. No reason why you can't but its just confusing.

Vector2D& operator+=(const &rhs)
{
X += rhs.X;
Y += rhs.Y;
return *this;
}

Vector2D * A = new Vector2D(1,1);
Vector2D * B = new Vector2D(1,1);
Vector2D &C = (*A) += *B; // Need to dereference them since they are pointers




okay, So i've tried deferenceing A and B and it works, but now adding two vectors looks like this:


int main(){
Vector2D * A = new Vector2D(1,1);
Vector2D * B = new Vector2D(1,1);
Vector2D * C = (*A) + (*B); // <-- Looks weird
C->Disp();
return 0;
}


modified unary operator function:



Vector2D * operator + (Vector2D & B){
this->X += + B.X;
this->Y += + B.Y;
return this;
}



I tried dereferencing the two vectors inside the function to avoid typing out C= (*A)+(*B)... but now it wont compile giving me the same
error.
Any reason why this is happening?




Hint: the expression A + B does not use a unary operator. The '+' operator is a binary operator.

If you want to implement a binary operator, what you really want to do is implement a binary operator.

Additionally, in C++ you are well advised to avoid using pointers. Using raw pointers in C++ is a code smell akin to a dead skunk on a pile of rotten eggs at the bottom of an outhouse. You would likely benefit by modifying your design to avoid using raw pointers.

Ad a general rule, if you find it very difficult to implement your design in C++ it's probably your design that's flawed. The language is trying to tell you very politely that what you're doing is unwise. You don't have to listen to it, it doesn't mind. You probably should, though.

Stephen M. Webb
Professional Free Software Developer

Why are you insisting on dynamically allocating your objects? Just use them as value types.

class Vector2D{
public:
double X;
double Y;

Vector2D(double IX, double IY) {
X = IX;
Y = IY;
}

void Disp(){
cout <<this-> X << "," ;
cout <<this-> Y <<endl;
}
};

Vector2D operator+(const Vector2D & lhs, const Vector2D & rhs) {
return Vector2D(lhs.X + rhs.X, lhs.Y + rhs.Y);
}

int main(){
Vector2D A(1,1);
Vector2D B(1,1);
Vector2D C = A + B;
C.Disp(); // or better yet provide an overload for operator<<
return 0;
}
Your problem, fundamentally, is that you are trying to use pointers in places where it makes no sense to use pointers.

When you add two ints, you get an int. Not an int*.

Similarly, when you add two Vector2Ds, you should get a Vector2D. Not a Vector2D*.

When you add two ints, the result is another int that did not exist before. The original ints are not affected. Similarly, again, for Vector2Ds.

'operator+' represents adding two values (we are overloading a binary operator here, BTW, not a unary one. One of the operands is the parameter, and the other is '*this').

We can write it as follows:


// The return type is 'Vector2D', because we are creating a Vector2D that did not exist before, and returning that value.
// We would use 'Vector2D&' to return, by reference, a Vector2D that already exists (i.e. not a copy).
Vector2D operator+(const Vector2D & rhs) {
// We must create the value that we will return.
Vector2D result;
// We can set its values to the sum of the values that we find in 'this' and 'B'.
result.X = X + rhs.X; // 'X' is the same as 'this->X'.
result.Y = Y + rhs.Y;
return result;
}


Notice the name "rhs" that I gave to the parameter. It stands for "right-hand side". When we overload a binary operator as a member function, the parameter is the right-hand side of the operator. The this-object is the left-hand side.

In the calling code, we are using pointers where it makes no sense to use them. Classes define a data type; we are supposed to be able to use a Vector2D the same basic way we use an int.

That means we normally create variables of type Vector2D, and only occasionally of Vector2D*, in places where we actually need to point to a Vector2D. Just like with ints.
The operator+ shown above allows us to add Vector2Ds just like ints, as long as we create them just like ints:


int main() {
Vector2D A(1, 1); // Notice there is no 'new' keyword.
Vector2D B(1, 1);
Vector2D C = A + B; // Exactly the same as with ints.
C.Disp(); '.' because we don't have a pointer.
}


To represent things like 'b +=a', we can overload the operator+=. This needs to return a reference - so that we can chain it and have it work the way it does for ints. It will modify 'b', the left-hand side of the operator - just like it would with ints. When we write it as a member function, the this-object represents the left-hand side, so we will modify the this-object and leave the other one alone. We return the this-object by reference.

So the whole thing looks like:


Vector2D& operator+=(const Vector2D& rhs) {
X += rhs.X; // We implement += in terms of the += for ints.
Y += rhs.Y;
return *this;
}


You will notice that operator+ and operator+= do similar work. How can we take advantage of this? Simple: we implement operator+ in terms of operator+=. The logic is as follows:

1) operator+ needs to create a new value that represents (*this) + rhs.
2) So we make a copy of *this, and add rhs to the copy. This is the value that we want to return.
3) We make the copy by just using the copy constructor. We can add rhs to the copy by using operator+= (that's what it means: "add to the left-hand side".

So now we simplify our operator+:


Vector2D operator+(const Vector2D& rhs) {
Vector2D result(*this); // That calls the copy constructor to make a copy of the this-object. We use '*this' to get a reference from the pointer.
result += rhs;
return result;
}


Although for something this simple, there is no real need to name the 'result' variable. We can also take advantage of the fact that operator+= returns a reference to its left-hand side (i.e., the copy that we made and then added to):


Vector2D operator+(const Vector2D& rhs) {
return Vector2D(*this) += rhs; // We can read this as "return the result of adding rhs to a copy of *this"
}

Why are you insisting on dynamically allocating your objects? Just use them as value types.



Okay.
Im making a 2D game that will be polygon based in C++(I've switched from java to C++).

In order to render polygons I usually start with the vector2D class(i also use the vector2D class to store vertices because i see no point in making another class called 'vertex' because vector2D already has X and Y components).


I then Usually make a shape class that stores a vector(dynamic array) of all the points(AKA, vector2D objects) .
In the Shape class i call collision functions and Rendering functions that use the dynamic array of vertices(Vector2D objects) for that particular shape.

The reason i want to have an array of pointers is so that it takes less time to process when i call rendering and collision functions each frame.
Why do you think pointers will take less time to process? Have you profiled it? If anything, using pointers would probably have the opposite effect. You're probably going to swiss cheese your cache with all those indirections.

This topic is closed to new replies.

Advertisement