12
votes

C ++ Plusieurs surcharges de l'opérateur pour le même opérateur

Je sais que je peux facilement répondre à cette question pour moi par génératine le code et voir s'il compilait. Mais puisque je ne pouvais pas trouver une question similaire, je pensais que c'était la connaissance de la peine d'être partagé. Dis que je surcharge de l'opérateur + de MyClass. Puis-je surcharger plusieurs fois. Surcharge différente pour différents types. Comme ceci: xxx

La raison pour laquelle je veux faire est que je construis une classe que je veux être aussi optimisée que possible. La performance est la plus grande préoccupation pour moi ici. SO CASTING ET À L'UTILISATION DE CAS DE COMMUTURE À L'INTÉRIEUR DE L'OPÉRATEUR + La fonction surchargée n'est pas une option. Je vous remarquerez, j'ai fait les deux surcharges en ligne. Supposons une seconde que le compilateur affirme effectivement mes surcharges, puis il est prédéterminé lors de la compilation de l'heure de compilation, et je sauvegarde l'appel à une fonction (par inlinge) + un scénario de cas de commutation complexe (en réalité, il y aura 5+ surcharges pour + opérateur), mais je suis toujours capable d'écrire facilement du code en utilisant des opérateurs arithmétiques de base. Donc, vais-je obtenir le comportement souhaité?


4 commentaires

Si vous êtes concerné par la performance, à partir d'un point de vue de la classe, retournez * Ceci via const myClass & sera meilleur. Maintenant, à partir d'un point de vue de l'utilisateur (sauf si vous ne compilez pas sur C ++ 0x), vous devez utiliser + = au lieu de + et = = Pour éviter les temporaires inutiles qui ne seront peut-être pas optimisés par certains compilateurs de merde.


Je ne sais pas pourquoi c'était voté à la fois. C'est une question parfaitement valable. (Le fait que vous trouviez que cette information ailleurs n'a aucune raison de ne pas trouver la réponse ici aussi.)


@paercebal: il met en œuvre la somme d'une somme, pas d'incrément. S'il impliquait opérateur + = , renvoyer une référence (après avoir modifié l'état interne), mais A + B n'est pas destiné à modifier le , mais produise plutôt une troisième valeur qui diffère des deux A et b .


@David Rodríguez - Dribesas: Omgomgomg. Tu as raison! Je ne sais pas comment j'ai négligé ça. +1 pour le commentaire.


3 Réponses :


12
votes

oui.


Ces fonctions de l'opérateur ne sont que des fonctions ordinaires avec les noms spéciaux opérateur @ . Il n'y a aucune restriction qu'ils ne peuvent pas être surchargés. En fait, l'opérateur <<< / code> utilisé par iostream est un opérateur avec plusieurs surcharges.


1 commentaires

Je me sens mal d'encombrer votre réponse avec un commentaire. Tache sur.



2
votes

Oui, vous pouvez surcharger des opérateurs comme celui-ci. Mais je ne suis pas sûr de ce que "cas de commutation" vous parlez de. Vous pouvez vivre avec une surcharge si vous avez un constructeur de conversion xxx pré> p> aucun interrupteur n'est nécessaire. Ceci est éligible si "myClass" représente logiquement un nombre. P>

Notez que vous devriez surcharger ces opérateurs par des fonctions non membres. Dans votre code 5 + C1 CODE> ne fonctionnerait pas, car il n'y a pas d'opérateur qui prend une INT de côté gauche. Ce qui suit fonctionnerait p>

inline const MyClass operator+(const MyClass &lhs, const MyClass &rhs) {
  // ...
}


2 commentaires

Johannes, ce constructeur de conversion implicite pourrait ne pas être une bonne idée. Pour une, les conversions implicites IME se révèlent généralement être une mauvaise idée tôt ou tard de toute façon, mais aussi parce qu'ElaDidan veut faire cela parce que "je construisais une classe que je veux être aussi optimisée que possible." Dans ce cas, les surcharges sont meilleures de toute façon.


Oh, et de copier de manière générale inline bla myClass :: dans myClass ne semble pas du tout comme vous. :)



10
votes

La forme canonique d'implémentation opérateur + () code> est une fonction libre basée sur opérateur + = () code>, que vos utilisateurs s'attendont quand vous aurez + code>. + = code> modifie son argument de gauche et devrait donc être membre. Le + code> traite ses arguments symétriquement et devrait donc être une fonction libre.

Quelque chose comme ça devrait faire: P>

//Beware, brain-compiled code ahead!
class MyClass {
public:
    MyClass& operator+=(const MyClass &rhs) const
    {
      // code for adding MyClass to MyClass
      return *this;
    }
    MyClass& operator+=(int rhs) const
    {
      // code for adding int to MyClass
      return *this;
    }
};


inline MyClass operator+(MyClass lhs, const MyClass& rhs) {
  lhs += rhs;
  return lhs;
}
inline MyClass operator+(MyClass lhs, int rhs) {
  lhs += rhs;
  return lhs;
}
// maybe you need this one, too
inline MyClass operator+(int lhs, const MyClass& rhs) {
  return rhs + lhs; // addition should be commutative
}


6 commentaires

+1 pour la bonne forme. Cependant, je voudrais probablement utiliser Boost.Pérateurs pour générer gratuitement les fonctions gratuites :)


TRÈS BASIC QN: Votre définition pour + nécessite que LHS soit un const, tandis que le code nécessite que vous écris LHS + = rhs. Il semble que vous ayez besoin de changer votre code ou votre définition. Ai-je raison?


@Anon: C'était un majeur de la mienne. Je suis allé la résolu et a profité de l'occasion pour ajouter mon avertissement standard.


Je pense que l'opérateur + devrait faire: myclass temp = lhs; temp + = rhs; Retour TEMP; . Sinon, si je fais: myClass A = B + C; , puis B changements.


@ Bill.not donc. LHS est reçu BYVAL. Depuis que nous retournons cette copie superficielle, nous ne modifions pas le paramètre d'origine et nous ne créons aucune instance inutile de myClass. Votre solution n'est valable que si nous recevons LHS BYREF (MyClass & LHS) et si nous surchargons l'opérateur "=";


@eladidan: myClass Temp = LHS invoque le Copie Constructor , pas l'opérateur d'affectation, mais sinon vous avez raison.