2012-09-04 2 views
1

noob ici. Ce qui suit est un fragment d'une définition de classe je suis dans un accross exemple du livre:opérateur [] ambiguïté résolution

double& operator[](int i); 
double operator[](int i) const; 

Ma question est: pourquoi est-ce pas ambigu? Lors de la compilation des fichiers du projet, le compilateur ne génère aucune erreur. En outre, dans ce qui suit (imaginez AnyClass contient un objet valarray<double> par exemple, et je veux y accéder directement):

AnyClass test; 
cout << test[2] 

version fait l'utilisation du compilateur?

Répondre

7

Ce n'est pas ambigu car le const fait partie de la signature et peut être utilisé pour la résolution de surcharge. Donc, si vous utilisez operator[] sur un objet non-const, il choisit la surcharge sans const car c'est la plus spécifique. Et si vous l'utilisez sur un objet const, il choisit la surcharge avec const car c'est la seule qui s'applique.

+1

Merci pour cela. Totalement oublié l'argument implicite. Et maintenant, il est logique de faire une version de l'opérateur [] pour les constantes. – Kurospidey

1

Si elle est appelée sur un objet const, la version const sera utilisée, sinon l'autre.

C'est ainsi que le compilateur résout l'ambiguïté.

+1

Ohhhh, maintenant je comprends. Merci pour votre réponse. La seconde ferait une version pour const au cas où je voudrais voir un certain élément par exemple. Je ne pouvais pas comprendre pourquoi ... Donc, cout utiliserait la première version non? Parce que test n'est pas une constante (et je pourrais aussi lui assigner une valeur car elle renvoie un double &). – Kurospidey

1
AnyClass test; 
const AnyClass const_test; 
std::cout << test[2];  // calls operator[](int) 
std::cout << const_test[2]; // calls operator[](int) const 
+1

Merci pour votre aide – Kurospidey

1

Pour comprendre cela, il faut la plupart du temps simplement pour se rendre compte qu'un const sur un argument est suffisant pour désambiguïser un appel:

#include <iostream> 

void foo(char* ptr) 
{ 
    std::cout << "mutable: " << ptr << std::endl; 
} 

void foo(const char* ptr) 
{ 
    std::cout << "const: " << ptr << std::endl; 
} 

int main() 
{ 
    const char* constHello = "hello"; 
    char mutableHello[] = "hello"; 
    foo(constHello); 
    foo(mutableHello); 
} 

Cette impression:

const: bonjour
mutable: bonjour

Le compilateur choisira la surcharge la moins restrictive possible. Donc, si vous utilisez un char* lorsqu'il y a une surcharge char*, c'est celui qu'il choisira; mais s'il n'y en a pas, le compilateur décidera que le convertir en const char* est une conversion viable (l'inverse n'est, évidemment, pas vrai).

Maintenant, la chose très simple est que toutes les méthodes passent un pointeur this comme premier paramètre de n'importe quelle fonction. Ce paramètre est caché pour des raisons de simplicité. Le const à la fin de la méthode qualifie l'argument this. Puisque, comme nous venons de le voir, un const sur un pointeur est suffisant pour désambiguïser les surcharges, cela fonctionnera effectivement.

+1

Merci pour votre réponse. – Kurospidey

Questions connexes