2009-07-07 8 views
4

je le code suivant:priorité de conversion en C++

Some functions: 

A::A(int i_a) {cout<<"int Ctor\n";}   //conversion constructor 

void h(double d) {cout<<"double param\n";} //f1 
void h(A a) {cout<<"A param\n";}    //f2 

Dans la fonction principale:

h(1); 

La fonction h (1) appelle est f1.

Ma question est pourquoi est-ce qu'il choisit de s'appeler cela. 1 est un int et nécessite donc conversion implicite en double. Il pourrait tout aussi bien convertir l'int en un A en utilisant le constructeur de conversion défini ci-dessus. Pourquoi n'ai-je pas d'erreur? Quelles sont les règles de priorité avec le casting?


N.b. Je l'ai posté au-dessus du code que je pense que ce sera nécessaire pour répondre à la question, mais au-dessous je poste le code entier:

#include <iostream> 
using namespace std; 
class B; 
class A { 
public: 
explicit A(const B&) {cout<<"Ctor through B\n";} 
A() {cout<<"Default Ctor\n";} 
A(int i_a) {cout<<"int Ctor\n";} 
operator int() {cout<<"A => int\n"; return 2;} 
}; 
class B { 
public: 
operator A() const {cout<<"B => A\n"; A a; return a;} 
}; 
void h(double d) {cout<<"double param\n";} 
void h(A a) {cout<<"A param\n";} 
void f(const A& a) 
{ 
cout<<"f function\n"; 
//Without the const it will never try to convert 
} 
void main() 
{ 
B b; 
cout <<"-----------------\n"; 
f(b); 
cout <<"-----------------\n"; 
h(1); 
} 
+2

Lors de l'écriture d'un code. N'ajoutez PAS de numéros de ligne - il est impossible de le compiler sans modification supplémentaire. Si vous souhaitez afficher un numéro de ligne, utilisez un commentaire. –

+0

numéros de ligne modifiés. – Tom

+0

En tant que sidenote, je n'appellerais pas "A :: A (int i_a)" un constructeur de conversion, juste un constructeur de A qui se trouve prendre un int en paramètre. De même, il est toujours bon d'appeler h (any h) avec ses paramètres exacts. S'il prend un A (la deuxième fonction), alors pourquoi ne pas lui passer un A? Par exemple h (A (1)); –

Répondre

14

Lorsque la résolution de surcharge est effectuée pour sélectionner le meilleur candidat de tous viables surcharges - le compilateur classe toutes les séquences de conversion pour chaque argument pour chaque candidat. Pour qu'une fonction gagne (être choisie comme meilleure candidate), ses rangs de conversion pour chaque argument doivent être meilleurs ou égaux aux rangs de conversion de chaque autre fonction pour cet argument ET au moins un rang de conversion doit être meilleur que tous les autres conversion de la fonction se classe pour un certain argument.

La conversion définie par l'utilisateur (qui utilise un constructeur ou un opérateur de distribution) a l'un des pires rangs possibles (seules les ellipses ont un rang inférieur). La conversion intégrale-flottante a un meilleur rang (voir ci-dessous pour une liste des classements).

Ainsi, le compilateur préfère convertir un int -> double (en utilisant une conversion standard) plutôt que de convertir un int -> A (en utilisant une conversion définie par l'utilisateur), et donc sélectionner f1. Edit: Bien que "Overload resolution" fonctionne en arrière-plan et la plupart du temps fait exactement ce que vous attendez (c'est-à-dire que la plupart des programmeurs n'auront pas besoin d'approfondir les détails techniques) - si vous voulez approfondir soyez averti que certains des coins les plus sombres de la résolution de surcharge sont considérés comme l'un des aspects les plus délicats pour les rédacteurs de compilateurs à obtenir exactement dans un compilateur C++) se référer à l'excellent C++ Templates: The Complete Guide by David Vandevoorde and Nicolai M. Josuttis qui fournit, en annexe B, l'une des meilleures introductions. la machinerie derrière la résolution de surcharge que j'ai lu.

Voici un extrait de B.2:

résolution de surcharge classe les fonctions candidats viables en comparant la façon dont chaque argument de l'appel correspond au paramètre correspondant des candidats. Pour un candidat à considéré comme meilleur qu'un autre, le meilleur candidat ne peut avoir aucun des paramètres suivants: ses paramètres sont moins bons que le paramètre correspondant dans l'autre candidat . ...

Compte tenu de ce premier principe, nous sommes à gauche avec en précisant à quel point un argument donné correspond au paramètre correspondant d'un candidat viable.En tant que première approximation, nous pouvons classer les correspondances possibles comme suit (du meilleur au pire ):

match parfait. Le paramètre a le type de l'expression, ou il a un type qui est une référence au type de l'expression (avec éventuellement ajouté const et qualificatifs volatiles).

Correspondance avec des ajustements mineurs. Ce comprend, par exemple, la désintégration d'une variable de tableau à un pointeur vers son premier élément, ou l'ajout de const pour correspondre à un argument de type int ** à un paramètre de type int const * const * .

Faites correspondre avec la promotion. La promotion est un type de conversion implicite que comprend la conversion des petits types entiers (tels que bool, char, court, et parfois énumérations) à int, unsigned int, long ou non signé long, et la conversion du flottant à double.

Correspond à des conversions standard uniquement. Ceci inclut toute sorte de conversion standard (comme int pour float) mais exclut l'appel implicite à un opérateur de conversion ou un constructeur de conversion .

Correspondance avec les conversions définies par l'utilisateur. Cela permet tout type de conversion implicite .

Correspondance avec ellipse. Un paramètre ellipse peut correspondre à presque n'importe quel type (mais les types de classe non-POD aboutissent à un comportement non défini ).

Mais c'est juste le début - si vous êtes intrigués - je vous invite à lire le livre, puis les parties pertinentes de la norme :)

0

Ajout de la norme (N4687)

en comparant les formes de base de séquences de conversion implicites (comme définis dans 16.3.3.1)

- (2,1) une séquence de conversion standard (16.3.3.1.1) est une meilleure séquence de conversion d'une séquence de conversion définie par l'utilisateur ou une séquence de conversion de l'ellipse, et

- (2.2) a défini par l'utilisateur La séquence de conversion (16.3.3.1.2) est une meilleure séquence de conversion qu'une séquence de conversion de l'ellipse (16.3.3.1.3).