2011-08-21 4 views
0

Je doute de la manière dont C++ lance les types lorsqu'il doit effectuer des calculs.comportement inattendu lors de la diffusion

Le code ci-dessous tel qu'il est (c'est-à-dire avec seulement la conversion en int sans cast en double) fonctionne et se construit sans problème. Si je définis ENABLE_DOUBLE_CAST ne construit pas et se plaint environ operator*. Est-ce que tu sais pourquoi?

Les doutes que j'ai sont 2:

  1. pourquoi sans que l'opérateur jeté à doubler, il est utilisé celui int dans une multiplication entre le double. Est-ce à cause de la distribution implicite?
  2. pourquoi avec le cast pour double activer (en ajoutant plus de clarté à la syntaxe) qui n'est pas pris en compte?

Merci

AFG

class CA{ 
    int _m; 
public: 
    CA(int a, int b){ 
    _m=a*b; 
    } 
    operator int(){ 
     std::cout<< "(CA int cast)" ; 
     return _m; 
    } 
#ifdef ENABLE_DOUBLE_CAST 
    operator double(){ 
     std::cout << "(CA double cat)"; 
     return 2.3 * _m; 
    } 
#endif 
}; 

int main(int argc, const char** argv){ 
    CA obj_2(10,20);     

    double total_1 = 100.0 * obj_2; 
    double total_2 = obj_2 * 100.0; 
    return 0; 
} 
+0

Vous avez entendu parler de la conversion définie par l'utilisateur, mais pas définie par l'utilisateur 'operator *'? Vous devez définir ce dernier. En fait, vous devez définir deux versions de 'operator *'. – Nawaz

Répondre

3

pourquoi sans que l'opérateur jeté à doubler, il est utilisé celui int dans une multiplication entre le double. Est-ce à cause de la distribution implicite?

Oui, c'est vrai.
Il utilise le operator int() pour convertir obj_2 à un int et utilise alors le

intégré operator*(double, int)

pourquoi avec les acteurs de double a permis (en ajoutant plus de clarté à la syntaxe) qui ne sont pas pris en considération?

Lorsque vous vendez des operator double() et operator int() pour votre classe, il crée une ambiguïté, que ce soit pour convertir obj_2 à un int ou double parce qu'il ya deux surcharges d'opérateur intégré qui peut utiliser, à savoir:

operator*(double, int) 
operator*(double, double) 

Suggestion:
vous devriez surcharger le operator* pour votre classe si vous voulez éviter cette p problème de conversions implicites et d'ambiguïté qui en découle.

operator*(double,CA) and 
operator*(CA,int) 
+0

Bonjour Als.Merci pour votre explication claire. J'ai toujours pensé que les opérateurs binaires intégrés C++ étaient limités aux arguments WITH THE MEME TYPE, donc operator * (double, double) ou operator * (int, int). Fondamentalement, vous dites que C++ fournit également ceux avec des types différents? –

+0

@Abruzzo Forte e Gentile: Oui, tous les opérateurs aithématiques pour les types incorporés sont fournis implicitement en C++. Vous pouvez les surcharger uniquement lorsque l'un des opérandes est une classe personnalisée. –

1

La raison est que à la fois que vous avez du code ambigu jette, le compilateur ne peut pas décider d'utiliser la distribution int ou la double distribution, les deux sont légales.

Les règles sur le casting implicite sont compliquées et je ne vais pas essayer de les répéter ici (cela prendrait littéralement des pages et des pages pour tout couvrir). Mais s'il est généralement admis que l'ajout de conversions implicites à vos classes est une mauvaise idée en raison de problèmes d'ambiguïté comme celui que vous avez vu. Si vous voulez utiliser CA avec opérateur *, il est préférable de définir l'opérateur * pour votre classe. Par exemple.

CA operator*(CA x, CA y) 
{ 
    ... 
} 

CA operator*(CA x, int y) 
{ 
    ... 
} 

CA operator*(CA x, double y) 
{ 
    ... 
} 

CA operator*(int x, CA y) 
{ 
    ... 
} 

CA operator*(double x, CA y) 
{ 
    ... 
} 
+0

Salut John. En lisant les autres posts, votre règle générale sur l'éviter est correcte. Question secondaire si cela ne vous dérange pas! Y a-t-il une situation où l'opérateur de distribution pourrait avoir un minimum d'aide? Si d'une manière générale, ils doivent être évités, pourquoi sont-ils toujours là? Tout cas d'utilisation au sommet de votre esprit? –

+0

Je suppose que le cas d'utilisation de commest est une conversion à une valeur booléenne, supposons avec votre classe 'CA' que vous vouliez l'utiliser comme un booléen, comme ceci' CA ca = ...; si (ca) ... '. C'est en fait assez difficile à faire sans introduire beaucoup d'ambiguïté ou de conversions surprenantes. Il peut être fait cependant, et il est appelé le _safe bool idiom_, Voici un bon lien pour plus de lecture http://www.artima.com/cppsource/safebool.html – john

+0

Merci Monsieur! Très appréciée! –