2010-11-12 6 views
10

d1 + 4 fonctionne mais 4 + d1 même si 4 peut être implicitement converti en un GMan. Pourquoi ne sont-ils pas équivalents?Pas de conversion implicite dans l'opérateur surchargé

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

Avez-vous essayé de demander [GMan] (http://stackoverflow.com/users/87234/gman)? – sbi

+0

sbi Non, je ne l'ai pas encore. –

+5

@ Le fan de GMan? Incroyable. Où sont mes fans (le cas échéant)? ': P' –

Répondre

12

Un appel x + y est traduit par le compilateur C++ dans l'une des deux appels suivants (selon que x est de type classe, et si une telle fonction existe):

  1. fonction membre

    x.operator +(y); 
    
  2. fonction libre

    operator +(x, y); 
    

maintenant C++ a une règle simple: pas de conversion implicite peut se produire avant un opérateur d'accès aux membres (.). De cette façon, x dans le code ci-dessus ne peut pas subir une conversion implicite dans le premier code, mais il peut dans le second. Cette règle a du sens: si x pouvait être implicitement converti dans le premier code ci-dessus, le compilateur C++ ne connaîtrait plus la fonction à appeler (c'est-à-dire à quelle classe il appartient) donc il devrait chercher tous classes existantes pour une fonction membre correspondante. Cela perturberait le système de type C++ et rendrait les règles de surcharge encore plus complexes et confuses.

3

This La réponse est correcte. Ces points impliquent alors la manière canonique d'implémenter de tels opérateurs:

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

Et ainsi de suite pour d'autres opérateurs.

Questions connexes