92 votes

Surcharge par type de retour

J'ai lu quelques questions ici sur SO à propos de ce sujet qui me semble encore confus. Je viens juste de commencer à apprendre le C++ et je n'ai pas encore étudié les templates ou la surcharge des opérateurs et autres.

Existe-t-il un moyen simple de surcharger

class My {
public:
    int get(int);
    char get(int);
}

sans modèles ou comportement étrange ? ou dois-je simplement

class My {
public:
    int get_int(int);
    char get_char(int);
}

?

3 votes

1 votes

@AdamV, j'aime beaucoup votre commentaire. Court mais tout à fait solide.

0 votes

@Adam V En fait, il existe déjà une telle ambiguïté en prenant l'adresse d'une fonction surchargée. Dans ce cas, il devrait y avoir une attente de type de l'expression. S'il n'y en a pas, le programme est mal formé. Et ceci est déjà implémenté. Je ne pense pas qu'il soit très difficile d'utiliser les mêmes règles pour implémenter la surcharge des fonctions par type de retour. Ainsi, dans votre exemple concret, l'ambiguïté sera levée par un cast du type retourné. L'instanciation avec int La valeur de retour ressemblera à ceci (int)get(9) et avec char comme ceci (char)get(9) .

113voto

Luchian Grigore Points 136646

Non, il n'y en a pas. Vous ne pouvez pas surcharger les méthodes en fonction du type de retour.

La résolution des surcharges tient compte de la signature de la fonction . Une signature de fonction est composée de :

  • nom de la fonction
  • cv-qualificateurs
  • types de paramètres

Et voici la citation :

1.3.11 signature

l'information sur une fonction qui participe à la surcharge (13.3) : sa liste de types de paramètres (8.3.5) et, si la fonction membre d'une classe, les qualificateurs cv (s'il y en a) sur la fonction elle-même et la classe dans laquelle la fonction membre est déclarée. elle-même et la classe dans laquelle la fonction membre est déclarée. [...]

Options :

1) changer le nom de la méthode :

class My {
public:
    int getInt(int);
    char getChar(int);
};

2) paramètre de sortie :

class My {
public:
    void get(int, int&);
    void get(int, char&);
}

3) Les gabarits... c'est exagéré dans ce cas.

18 votes

Vous ne pouvez pas surcharger une fonction normale sur le type de retour, mais le compilateur choisira entre les opérateurs de conversion en fonction du type résultant ; vous pouvez tirer parti de cela pour créer un proxy qui agit effectivement comme si vous aviez surchargé sur le type de retour.

0 votes

Je suis en train de lire sur les modèles. Pourriez-vous en faire un exemple ici ? Pas de My<char> var; var.get(3); fonctionne dans ce cas ?

2 votes

@JeffPigarelli La solution des modèles signifie des modèles pour les membres : My::get<T>(int) . C'est une alternative valable Si 1) vous devez gérer un grand nombre de types différents, tous avec le même code de base (par ex. boost::lexical_cast<T>( someStringValue ) ou vous devez être en mesure d'appeler ces fonctions à partir d'un autre modèle ( myMy.get<T>( i ) , donde T est un argument de cet autre modèle. Sinon, comme le dit Luchian, ils sont exagérés.

86voto

James Kanze Points 96599

C'est possible, mais je ne suis pas sûr que ce soit une technique que je recommande pour débutants. Comme dans d'autres cas, lorsque vous voulez que le choix des fonctions dépende de l'utilisation de la valeur de retour, vous utilisez un proxy. dépende de la manière dont la valeur de retour est utilisée, vous utilisez un proxy ; définissez d'abord fonctions comme getChar y getInt alors un générique get() qui renvoie un Proxy comme ceci :

class Proxy
{
    My const* myOwner;
public:
    Proxy( My const* owner ) : myOwner( owner ) {}
    operator int() const
    {
        return myOwner->getInt();
    }
    operator char() const
    {
        return myOwner->getChar();
    }
};

Étendez-le à autant de types que vous le souhaitez.

11 votes

+1, bien qu'il s'agisse d'un cas particulier, l'opérateur de conversion est en fait surchargé sur le type de retour, et peut être utilisé pour obtenir cette fonctionnalité à peu près partout.

3 votes

@MatthieuM. A peu près partout, mais avec les réserves habituelles concernant les conversions implicites. Vous courez le risque d'introduire des ambiguïtés qui n'existeraient pas autrement. Dans le cas d'un Proxy, cependant, je pense que le risque est mineur - vous n'aurez pas d'instances du type Proxy en dehors du cas où vous voulez la conversion implicite. Notez également que la conversion dans le proxy compte comme une conversion définie par l'utilisateur. Si vous avez besoin de std::string et le mandataire ne propose que operator char const*() ça ne va pas marcher.

0 votes

Pourquoi utiliser le proxy ici, je ne vois pas de cas où le proxy est indispensable. Pouvez-vous en fournir un ? Merci !

10voto

Mike Seymour Points 130519

Non, vous ne pouvez pas surcharger par type de retour ; seulement par types de paramètres, et qualificatifs const/volatile.

Une alternative serait de "retourner" en utilisant un argument de référence :

void get(int, int&);
void get(int, char&);

bien que j'utiliserais probablement soit un modèle, soit des fonctions portant un nom différent, comme dans votre deuxième exemple.

0 votes

À la manière de l'API EFI où le type de retour est un int code d'erreur.

1 votes

Attention, les types char et int peuvent être implicitement convertis.

0 votes

Si vous utilisez un modèle, vous devrez probablement fournir explicitement le type entre crochets lorsque vous l'utiliserez, n'est-ce pas ? Parce que dans de nombreuses circonstances, le compilateur ne serait pas en mesure de connaître le type exact auquel vous le traitez ?

2voto

sepp2k Points 157757

Il n'y a aucun moyen de surcharger par type de retour en C++. Sans utiliser de modèles, l'utilisation de get_int y get_char sera le mieux que vous puissiez faire.

0 votes

Juste pour être sûr : quelque chose comme template <class T> T get(int) fonctionnerait ?

4 votes

Oui, @Niklas, mais il faudrait l'appeler en tant que get<int> o get<char> ce qui ne vous apporte pas grand-chose. get_int y get_char si vous n'utilisez pas également d'autres fonctionnalités du modèle.

0 votes

@Rob : Eh bien, le compilateur peut déterminer T si vous avez quelque chose comme T get(T) . Si vous appelez get('a') le compilateur déduit que T est un char et vous n'avez pas besoin d'appeler explicitement get<char>('a') . Je ne suis toujours pas sûr que ce soit la norme, même si je pense que ça l'est. Pour votre information, GCC et Clang supportent tous deux cette fonctionnalité.

2voto

Frecklefoot Points 463

Vous ne pouvez pas surcharger les méthodes en fonction des types de retour. Votre meilleure chance est de créer deux fonctions avec une syntaxe légèrement différente, comme dans votre deuxième extrait de code.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X