2010-11-12 22 views
10

d1 + 4 funciona pero 4 + d1 aunque 4 se puede convertir implícitamente en un GMan. ¿Por qué no son equivalentes?Ninguna conversión implícita en el operador sobrecargado

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; 
} 
+4

¿Has intentado preguntar a [GMan] (http://stackoverflow.com/users/87234/gman)? – sbi

+0

sbi No, aún no lo he hecho. –

+5

@ ¿Fan de GMan? Asombroso. ¿Dónde están mis fanáticos (si hay alguno)? ': P' –

Respuesta

12

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

  1. función miembro

    x.operator +(y); 
    
  2. función gratuito

    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 esta forma, x en el código anterior no puede sufrir una conversión implícita en el primer código, pero sí 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++ no sabría más que funcionan para llamar (es decir, qué clase pertenece a) por lo que tendría que buscar todo las clases existentes para una función de miembro coincidente. Eso causaría estragos en el sistema de tipos de C++ y haría las reglas de sobrecarga aún más complejas y confusas.

3

This La respuesta es correcta. Esos puntos implican la forma canónica de implementar dichos 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 otros operadores.

Cuestiones relacionadas