2009-10-28 11 views
9

J'ai des problèmes de surcharge en C++. À titre d'exemple du problème, j'ai une classe avec un certain nombre de méthodes étant surchargées, et chaque méthode ayant un paramètre avec un type de données différent. Ma question: existe-t-il un ordre particulier dans la classe où ces méthodes devraient apparaître, pour s'assurer que la bonne méthode est appelée en fonction de son type de données de paramètres?Fonction/Méthode Surcharge C++: Confusion de type de données?

class SomeClass{ 
    public: 
    ... 
    void Method(bool paramater); 
    void Method(std::string paramater); 
    void Method(uint64_t paramater); 
    void Method(int64_t paramater); 
    void Method(uint8_t paramater); 
    void Method(int8_t paramater); 
    void Method(float paramater); 
    void Method(double paramater); 
    void Method(ClassXYZ paramater); 
} 

Je remarqué qu'il y avait problème parce que lors de l'exécution:

Method("string"); 

il appelait:

Method(bool paramater); 

Répondre

5

La chaîne littérale "string" est de type const char[] qui peut être converti en bool implicitement. Il s'agit du meilleur candidat à la conversion pour l'une de vos fonctions surchargées, bien qu'il ne soit pas le plus utile.

Si votre intention était d'avoir des chaînes littérales traitées par la surcharge en prenant un std::string, alors vous devez ajouter une surcharge prendre une const char* et faire la mise en œuvre appellent la version std::string.

+0

C'EST COMPLÈTEMENT ANNOYANT. Cette règle de résolution ne répond pas à un concept aussi fondamental. Peut-être que l'OP «par ordre de déclaration» approche intuitive ferait un meilleur travail. –

4

La commande est sans importance. Le problème ici est que lorsque vous appelez

Method("string"); 

vous passez un const char []. Cela sera converti en bool implicitement. Ce que vous voulez faire est de passer une chaîne std :: explicitement:

Method(std::string("string")); 
+0

Ne pas lancer; construction! std :: string ("string") (ou faire une surcharge à char * comme ci-dessus) –

+0

Bien sûr; édité, merci. – Tomas

23

La commande ne fait aucune différence. La méthode à appeler est sélectionnée en analysant les types d'arguments et en les associant aux types de paramètres. Dans le cas où il n'y a pas de correspondance exacte, la méthode correspondant le mieux est sélectionnée. Dans votre cas, il s'agit de la méthode bool.

Vous fournissez un argument de type const char[7]. Selon les règles de surcharge C++, le meilleur chemin ici est de laisser const char[7] se désintégrer en const char * puis de le convertir en bool en utilisant une conversion standard. Le chemin avec la conversion à std::string est considéré comme pire, car il impliquerait une conversion définie par l'utilisateur de const char * à std::string. Généralement, les conversions définies par l'utilisateur perdent le processus de résolution de surcharge en conversions standard. C'est ce qui se passe dans votre cas aussi.

Si vous avez besoin std::string version à l'appeler ici, fournissent une surcharge explicite pour le type const char *, et déléguer l'appel à std::string la version en convertissant l'argument std::string explicitement le type

void Method(const char *paramater /* sic! */) 
{ 
    Method(std::string(paramater)); 
} 
+1

sous-défini -> défini par l'utilisateur? – jalf

+0

Fixé. Je vous remercie. – AnT

1

Comme Charles a déjà souligné, cela se produit en raison d'une conversion implicite non désirée. Si vous voulez éviter cela, utilisez un constructeur std :: string: Method(std::string("string")); ou jeté à std :: string:

Method(static_cast<std::string>("string")); 

Cependant, l'ordre de vos déclarations est sans importance.Vérifiez également l'orthographe du mot "paramètre";)

1

Mis à part le problème de chaîne, il y en a un autre. int64_t et int8_t sont (habituellement) typedefs. Comme les typedefs ne sont que des alias, ils peuvent faire référence au même type, auquel cas la surcharge ne fonctionnera pas. Mais c'est plutôt improbable dans votre cas. je voulais juste le mentionner.

2

Vous ne répondez pas à votre question mais, par simple curiosité, y a-t-il une raison cachée de ne pas utiliser une méthode template au lieu de définir une version de surcharge pour chaque type?

class SomeClass 
{ 
    public: 
    ... 
    template <typename T> 
    void Method(T paramater); 
}; 
+0

C'est sympa car cela va désactiver les conversions automatiques qui commencent à devenir bizarres. Vous pouvez également définir votre méthode pour les quelques spécialisations que vous avez l'intention de prendre en charge. –

1

Vous pouvez ajouter un explict mot-clé de manière à prendre l'argument prévu.