Pregunta

funciona d1 + 4 pero no 4 + d1 a pesar de que 4 se puede convertir implícitamente a un GMan. Por qué no son equivalentes?

struct GMan
{
    int a, b;

    GMan() : a(), b() {}
    GMan(int _a) : a(_a), b() {}
    GMan(int _a, int _b) : a(_a), b(_b) {}

    GMan operator +(const GMan& _b)
    {
         GMan d;
         d.a = this->a + _b.a;
         d.b = this->b + _b.b;
         return d;
    }
};

int main()
{
    GMan d1(1, 2), d(2);
    GMan d3;
    d3 = d1 + 4; 
    d3 = 4 + d1;
}
¿Fue útil?

Solución

A x + y llamada es traducida por el compilador de C ++ en cualquiera de las dos llamadas siguientes (dependiendo de si x es de tipo de clase, y si existe una función de este tipo):

  1. Función de miembro

    x.operator +(y);
    
  2. Función de Libre

    operator +(x, y);
    

Ahora C ++ tiene una regla simple: no hay conversión implícita puede ocurrir antes de que un operador de acceso miembro (.). De esa manera, x en el código anterior no puede someterse a una conversión implícita en el primer código, pero puede en el segundo.

Esta regla tiene sentido: si x se podría convertir implícitamente en el primer código anterior, el compilador de C ++ sería no saber nada más, que la función de llamada (es decir qué clase pertenece a) por lo que tendría que buscar todas las clases existentes para una función miembro correspondiente. Eso sería hacer estragos en el sistema de tipo de C ++ y hacer las reglas sobrecargar aún más complejo y confuso.

Otros consejos

Esta respuesta es correcta. entonces esos puntos implican la forma canónica de la implementación de este tipo de operadores:

struct GMan
{
    int a, b;

    /* Side-note: these could be combined:
    GMan():a(),b(){}
    GMan(int _a):a(_a),b(){}
    GMan(int _a, int _b):a(_a),b(_b){}
    */
    GMan(int _a = 0, int _b = 0) : a(_a), b(_b){} // into this

    // first implement the mutating operator
    GMan& operator+=(const GMan& _b)
    {
        // the use of 'this' to access members
        // is generally seen as noise
        a += _b.a;
        b += _b.b;

        return *this;
    }
};

// then use it to implement the non-mutating operator, as a free-function
// (always prefer free-functions over member-functions, for various reasons)
GMan operator+(GMan _a, const GMan& _b)
{
    _a += b; // code re-use
    return _a;
}

Y así sucesivamente para los otros operadores.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top