views:

174

answers:

2

I need help on finding the problem using a custom c++ class to manage 3D positions. Here is the relevant code from the class

  Punto operator+(Punto p){
    return Punto(this->x + p.x, this->y + p.y, this->z + p.z);
  }

  Punto operator+(Punto *p){
    return Punto(this->x + p->x, this->y + p->y, this->z + p->z);
  }

  Punto operator-(Punto p){
    return Punto(this->x - p.x, this->y - p.y, this->z - p.z);
  }

  Punto operator-(Punto *p){
    return Punto(this->x - p->x, this->y - p->y, this->z - p->z);
  }

  Punto *operator=(Punto p){
    this->x = p.x;
    this->y = p.y;
    this->z = p.z;
    return this;
  }

  Punto *operator=(Punto *p){
    this->x = p->x;
    this->y = p->y;
    this->z = p->z;
    return this;
  }

I'm using it here like this:

p = fem->elementoFrontera[i]->nodo[0] - fem->elementoFrontera[i]->nodo[1];

Where nodo[i] is a Punto*, and it compiles fine, but when I try to do:

p = fem->elementoFrontera[i]->nodo[0] + fem->elementoFrontera[i]->nodo[1];

The compiler says:

In member function void mdTOT::pintarElementosFrontera()': error: invalid operands of types Punto*' and Punto*' to binary operator+'

+5  A: 

The first one compiles fine because you can subtract pointers in C/C++, but not add pointers. But in any case it doesn't do what you need - it doesn't use your overloaded operator. Since your operators are defined in a class, you need to operate on class instances, not on pointers. So, change to something like

Punto p = *(fem->elementoFrontera[i]->nodo[0]) + *(fem->elementoFrontera[i]->nodo[1]);

Another thing - you should use class references, not values, in operator definition. E.g.

 Punto& operator+(const Punto& p) {

EDIT. To simplify the code, you can create an accessor function, like this:

const Punto& NodoRef(int i, int j) {
  return *(fem->elementoFronteria[i]->Nodo[j]);
}

and then your code becomes as clean as

p = NodoRef(i,0) + NodoRef(i,1);

The NodoRef may be defined in your fem class, or outside. Just make sure the object fem is alive in the scope where you use the NodoRef.

Igor Krivokon
Anyway to make it look prettier? I mean, that's ugly to be deferencing code on each operation, don't you think?
Luis
It's a matter of taste. I prefer explicit code and no hidden magic. If I have a pointer, I know need to dereference it before applying any operations.
Igor Krivokon
Technically, you can declare out-of-class operator+ with 2 parameters, defined on pointers to Punto. But it needs to return an object. So, it's ugly: the + operator doesn't return the same type as operands. I would not recommend doing this.
Igor Krivokon
Regarding how to make it prettier: I would create an accessor function that returns a const reference to a Punto. Let me update the answer...
Igor Krivokon
+1  A: 

The first version works because "-" does normal pointer arithmetic in this case, it doesn't use any of your overloaded operators. "+" is not defined on normal pointers, so you get an error. To make it use the overloaded version, dereference the first pointer:

p = *fem->elementoFrontera[i]->nodo[0] - fem->elementoFrontera[i]->nodo[1];

Dereferencing both pointers should also work since you have both types of overloads, but you should change your operator definitions to use const references in this case:

Punto operator+(const Punto &p){
   ...
}

This way the objects are not copied every time you use "+".

Basically you want to do something like this:

const Punto operator+(Punto *left, Punto *right); // not allowed

But overloading a free function operator+ that takes two pointers and adds them in a suitable way does not work, because at least one of the parameters needs to be of enum or class type. There is no operator overloading for primitive types, and pointers count as such.

sth
Same here, it's ugly to be deferencing everywhere, any hints on making it look simplier?
Luis
Could you just store Punto objects instead of pointers to them in your elementoFrontera vector? Then the "+" would work as expected...
sth
The idea is for it to point to some other place where the Punto objects are saved.
Luis