J'ai lu qu'un opérateur surchargé déclaré comme fonction membre est asymétrique car il ne peut avoir qu'un seul paramètre et l'autre paramètre passé automatiquement est le this
pointeur. Il n'existe donc aucune norme pour les comparer. D'autre part, l'opérateur surchargé déclaré comme a friend
est symétrique car nous passons deux arguments du même type et par conséquent, ils peuvent être comparés.
Ma question est la suivante: lorsque je peux encore comparer la valeur d'un pointeur à une référence, pourquoi les amis sont-ils préférés? (l'utilisation d'une version asymétrique donne les mêmes résultats qu'une version symétrique) Pourquoi les algorithmes STL n'utilisent-ils que des versions symétriques?
Réponses:
Si vous définissez votre fonction surchargée d'opérateur en tant que fonction membre, le compilateur traduit des expressions comme
s1 + s2
ens1.operator+(s2)
. Cela signifie que la fonction membre surchargée par l'opérateur est appelée sur le premier opérande. C'est ainsi que fonctionnent les fonctions membres!Mais que faire si le premier opérande n'est pas une classe? Il y a un problème majeur si nous voulons surcharger un opérateur où le premier opérande n'est pas un type de classe, disons plutôt
double
. Vous ne pouvez donc pas écrire comme ça10.0 + s2
. Cependant, vous pouvez écrire une fonction membre surchargée d'opérateur pour des expressions telles ques1 + 10.0
.Pour résoudre ce problème d' ordre , nous définissons la fonction surchargée d'opérateur comme
friend
SI elle a besoin d'accéder auxprivate
membres. Faites-lefriend
UNIQUEMENT lorsqu'il a besoin d'accéder aux membres privés. Sinon, faites simplement en sorte que ce soit une fonction non-membre ami pour améliorer l' encapsulation!Lisez ceci:
Un léger problème d'ordre dans les opérandes
Comment les fonctions non membres améliorent l'encapsulation
la source
friend
seulement quand il a besoin d'accéder aux membres privés..et quand vous n'avez pas / êtes ennuyé d'écrire des accesseurs, non?a/b
.friend
est de les implémenter en termes d'opérateurs d'affectation d'opération (qui seront presque certainement des membres publics). Par exemple, vous pouvez définirT T::operator+=(const T &rhs)
comme membre, puis définir non-membreT operator(T lhs, const T &rhs)
commereturn lhs += rhs;
. La fonction non membre doit être définie dans le même espace de noms que la classe.Ce n'est pas nécessairement une distinction entre
friend
les surcharges d'opérateurs et les surcharges d'opérateurs de fonctions membres, comme c'est le cas entre les surcharges d'opérateurs globaux et les surcharges d'opérateurs de fonctions membres.Une raison de préférer une surcharge d'opérateur global est si vous souhaitez autoriser les expressions où le type de classe apparaît sur le côté droit d'un opérateur binaire. Par exemple:
Cela ne fonctionne que s'il y a une surcharge d'opérateur global pour
Notez que la surcharge d'opérateur global n'a pas nécessairement besoin d'être une
friend
fonction. Cela n'est nécessaire que s'il a besoin d'accéder à des membres privés deFoo
, mais ce n'est pas toujours le cas.Quoi qu'il en soit, si
Foo
seulement il y avait une surcharge d'opérateur de fonction membre, comme:... alors nous ne pourrions avoir d'expressions où une
Foo
instance apparaît à gauche de l'opérateur plus.la source