overload operator equal assignment c++ struct typedef operator-keyword

operator - Sobrecarga de operadores en estructuras typedef(c++)



equal operator c++ (4)

Quiero hacer una estructura typedef llamada pos (desde posición) que almacene las coordenadas xey. Estoy intentando sobrecargar algunos operadores para esta estructura, pero no compila.

typedef struct { int x; int y; inline pos operator=(pos a) { x=a.x; y=a.y; return a; } inline pos operator+(pos a) { return {a.x+x,a.y+y}; } inline bool operator==(pos a) { if (a.x==x && a.y== y) return true; else return false; } } pos;

También quería saber la diferencia entre esto:

inline bool operator==(pos a) { if(a.x==x && a.y== y) return true; else return false; }

Y esto:

bool operator==(pos a) const { if(a.x==x && a.y== y) return true; else return false; }


  1. bool operator == (pos a) const {- este método no cambia los elementos del objeto.
  2. bool operator == (pos a) {- puede cambiar los elementos del objeto.

En lugar de typedef struct { ... } pos; deberías estar haciendo struct pos { ... }; . El problema aquí es que está usando el nombre de tipo pos antes de que se defina. Al mover el nombre a la parte superior de la definición de estructura, puede usar ese nombre dentro de la propia definición de estructura.

Además, typedef struct { ... } name; el patrón es un C-ismo, y no tiene mucho lugar en C ++.

Para responder a su pregunta sobre en inline , no hay diferencia en este caso. Cuando se define un método dentro de la definición de estructura / clase, se declara implícitamente en línea. Cuando especifica explícitamente en inline , el compilador efectivamente lo ignora porque el método ya está declarado en línea.

(los métodos en inline no desencadenarán un error del enlazador si el mismo método está definido en varios archivos de objetos; el enlazador simplemente ignorará todos menos uno de ellos, suponiendo que todos sean la misma implementación. Este es el único cambio garantizado en el comportamiento con en línea métodos. Hoy en día, no afectan la decisión del compilador sobre si alinear o no las funciones, sino que simplemente facilitan la implementación de la función en todas las unidades de traducción, lo que le da al compilador la opción de alinear la función, si decide que sería beneficioso. para hacerlo.)


prueba esto:

struct Pos{ int x; int y; inline Pos& operator=(const Pos& other){ x=other.x; y=other.y; return *this; } inline Pos operator+(const Pos& other) const { Pos res {x+other.x,y+other.y}; return res; } const inline bool operator==(const Pos& other) const { return (x==other.x and y == other.y); } };


El desglose de su declaración y sus miembros está algo desordenado:

Eliminar el typedef

El typedef no es obligatorio ni deseado para las declaraciones de clase / estructura en C ++. Sus miembros no tienen conocimiento de la declaración de pos como está escrita, que es esencial para su falla de compilación actual.

Cambia esto:

typedef struct {....} pos;

A esto:

struct pos { ... };

Eliminar líneas extrañas

Ambos declaran y definen sus operadores miembros dentro de la definición de la clase en sí. La palabra clave en inline no es necesaria siempre que sus implementaciones permanezcan en su ubicación actual (la definición de clase)

Devuelve referencias a *this cuando corresponda

Esto está relacionado con una gran cantidad de construcciones de copia dentro de su implementación que no deberían hacerse sin una razón fuerte para hacerlo. Está relacionado con la expresión ideológica de lo siguiente:

a = b = c;

Esto asigna c a b , y el valor resultante b se asigna a a . Esto no es equivalente al siguiente código, al contrario de lo que pueda pensar:

a = c; b = c;

Por lo tanto, su operador de asignación debe implementarse como tal:

pos& operator =(const pos& a) { x = a.x; y = a.y; return *this; }

Incluso aquí, esto no es necesario. El operador predeterminado de copia-asignación hará lo anterior para usted de forma gratuita (¡y codifique!).

Nota : hay ocasiones en las que se debe evitar lo anterior a favor de la expresión de copia / intercambio . Aunque no es necesario para este caso específico, puede verse así:

pos& operator=(pos a) // by-value param invokes class copy-ctor { this->swap(a); return *this; }

Luego se implementa un método de intercambio:

void pos::swap(pos& obj) { // TODO: swap object guts with obj }

Usted hace esto para utilizar el copy-ctor de clase para hacer una copia, luego utiliza el intercambio seguro de excepciones para realizar el intercambio. El resultado es que la copia entrante sale (y destruye) las agallas viejas de su objeto, mientras que su objeto asume la propiedad de eso. Lea más sobre el modismo de copiar / intercambiar aquí , junto con los pros y los contras.

Pasar objetos por referencia constante cuando sea apropiado

Todos sus parámetros de entrada a todos sus miembros están haciendo copias de lo que se está pasando en invocar. Si bien puede ser trivial para un código como este, puede ser muy costoso para tipos de objetos más grandes. Un ejemplo se da aquí:

Cambia esto:

bool operator==(pos a) const{ if(a.x==x && a.y== y)return true; else return false; }

Para esto: (también simplificado)

bool operator==(const pos& a) const { return (x == a.x && y == a.y); }

No se hacen copias de nada , lo que resulta en un código más eficiente.

Finalmente, al responder a su pregunta, ¿cuál es la diferencia entre una función miembro u operador declarado como const y uno que no lo es?

Un miembro de const declara que la invocación de ese miembro no modificará el objeto subyacente (no obstante, las declaraciones mutables). Solo las funciones miembro de const pueden invocarse contra objetos const , o const referencias y punteros. Por ejemplo, su operator +() no modifica su objeto local y, por lo tanto, debe declararse como const . Su operator =() modifica claramente el objeto local y, por lo tanto, el operador no debe estar const .

Resumen

struct pos { int x; int y; // default + parameterized constructor pos(int x=0, int y=0) : x(x), y(y) { } // assignment operator modifies object, therefore non-const pos& operator=(const pos& a) { x=a.x; y=a.y; return *this; } // addop. doesn''t modify object. therefore const. pos operator+(const pos& a) const { return pos(a.x+x, a.y+y); } // equality comparison. doesn''t modify object. therefore const. bool operator==(const pos& a) const { return (x == a.x && y == a.y); } };

EDIT OP quería ver cómo funciona una cadena de operadores de asignación. Lo siguiente demuestra cómo esto:

a = b = c;

Es equivalente a esto:

b = c; a = b;

Y que esto no siempre equivale a esto:

a = c; b = c;

Código de muestra :

#include <iostream> #include <string> using namespace std; struct obj { std::string name; int value; obj(const std::string& name, int value) : name(name), value(value) { } obj& operator =(const obj& o) { cout << name << " = " << o.name << endl; value = (o.value+1); // note: our value is one more than the rhs. return *this; } }; int main(int argc, char *argv[]) { obj a("a", 1), b("b", 2), c("c", 3); a = b = c; cout << "a.value = " << a.value << endl; cout << "b.value = " << b.value << endl; cout << "c.value = " << c.value << endl; a = c; b = c; cout << "a.value = " << a.value << endl; cout << "b.value = " << b.value << endl; cout << "c.value = " << c.value << endl; return 0; }

Salida

b = c a = b a.value = 5 b.value = 4 c.value = 3 a = c b = c a.value = 4 b.value = 4 c.value = 3