2009-03-13 21 views
8

Pouvez-vous me dire pourquoi le code suivant me donne l'erreur suivante - appel de surcharge « C (int) » est ambiguC++ - surcharge Constructor - privés et publics

Je pense que depuis C (char x) est privé, seul le Ctor (float) est visible de l'extérieur et devrait être appelé en convertissant int en float.

Mais ce n'est pas le cas.

class C 
{ 
    C(char x) 
    { 
    } 
public: 
    C(float t) 
    { 
    } 
}; 

int main() 
{ 
    C p(0); 
} 

Répondre

18

Ceci est discuté dans "Effective C++" par Scott Meyer. La raison pour laquelle cela est ambigu est qu'ils voulaient s'assurer que changer simplement la visibilité d'un membre ne changerait pas la signification du code déjà existant ailleurs.

Sinon, supposons que votre classe C se trouve dans un en-tête quelque part. Si vous avez un membre C (int) privé, le code que vous présentez appellera C (float). Si, pour une raison quelconque, le membre C (int) était rendu public, l'ancien code appellerait soudainement ce membre, même si ni l'ancien code ni la fonction qu'il appelait n'avaient changé.

EDIT: raisons plus:

Pire encore, supposons que vous aviez les 2 fonctions suivantes:

C A::foo() 
{ 
    return C(1.0); 
} 

C B::bar() 
{ 
    return C(1.0); 
} 

Ces deux fonctions peuvent appeler différentes fonctions selon que ce soit foo ou bar a été déclaré comme ami de C, ou si A ou B en hérite. Ayant identique code appel différentes fonctions est effrayant.

(C'est probablement pas aussi bien mis en discussion de Scott Meyer, mais c'est l'idée.)

+1

Hmm, cela semblait être une bonne explication en premier. Mais ... il est toujours possible de créer la classe _without_ un int-ctor, puis plus tard _add_ que ctor si ancien code commence soudainement à appeler le nouveau membre ... Donc cette protection crée seulement un faux sentiment de sécurité. –

+0

Bon point. J'ajouterai plus. –

7

0 est un type int. Comme il peut être implicitement converti en float ou char de manière égale, l'appel est ambigu. La visibilité n'est pas pertinente à ces fins.

soit mis 0.0, 0. ou 0.0f, ou se débarrasser du tout constructeur C(char).

Edit: partie pertinente de la norme, l'article 13.3:

3) [...] Mais, une fois que les fonctions candidats et des listes d'arguments ont été identifiés, la sélection de la meilleure fonction est la même dans tous les cas:

  • en premier lieu, un sous-ensemble des fonctions-les candidats qui ont le bon nombre d'arguments et répondent à certaines autres conditions est sélectionnée pour former un ensemble de fonctions viables (13.3.2).
  • Ensuite, la meilleure fonction viable est sélectionnée en fonction des séquences de conversion implicites (13.3.3.1) nécessaires pour faire correspondre chaque argument au paramètre correspondant de chaque fonction viable.

4) Si une meilleure fonction viable existe et est unique, la résolution de surcharge réussit et la produit comme résultat. Sinon, la résolution de surcharge échoue et l'invocation est mal formée. Lorsque la résolution de surcharge réussit et que la meilleure fonction viable n'est pas accessible (clause 11) dans le contexte dans lequel elle est utilisée, le programme est mal formé.

Notez que la visibilité ne fait pas partie du processus de sélection.

+0

Vous n'avez pas expliqué pourquoi la confidentialité n'incline pas la résolution de surcharge. –

+0

+1 Ceci est la moitié de l'histoire, mais n'aborde pas la visibilité. –

+0

Passage à la catégorie des citations standard. –

-1

Je ne pense pas que:

C p(0); 

est convertie en:

C(float t) 

vous avez probablement besoin de le faire:

C p(0.0f); 
+0

Non, ce n'est pas le problème. Une conversion implicite de '0' en float * does * existe. –