Je comprends plus la surcharge des opérateurs, à l'exception des opérateurs d'accès des membres ->
, .*
, ->*
etc.
En particulier, qu'est-ce qui est passé à ces fonctions d'opérateur et que faut-il renvoyer?
Comment la fonction d'opérateur (par exemple operator->(...)
) sait-elle à quel membre il fait référence? Peut-il savoir? A-t-il même besoin de savoir?
Enfin, y a-t-il des considérations const à prendre en compte? Par exemple, lorsque vous surchargez quelque chose comme operator[]
, vous aurez généralement besoin à la fois d'une version const et non const. Les opérateurs d'accès aux membres nécessitent-ils des versions const et non const?
const
et les non-const
versions deoperator->
ne sont pas obligatoires , mais fournir les deux peut être utile.->*
et.*
. En fait, il ne les mentionne même pas! Je pense qu'ils sont trop rares pour être dans une FAQ, mais je serais heureux de lier cette question à la FAQ. Veuillez ne pas fermer cela comme une dupe de la FAQ!Réponses:
->
C'est le seul qui soit vraiment délicat. Il doit s'agir d'une fonction membre non statique et ne prend aucun argument. La valeur de retour est utilisée pour effectuer la recherche de membre.
Si la valeur de retour est un autre objet de type classe, pas un pointeur, la recherche de membre suivante est également gérée par une
operator->
fonction. C'est ce qu'on appelle le «comportement de recherche en avant». Le langage enchaîne lesoperator->
appels jusqu'à ce que le dernier renvoie un pointeur.->*
Celui-ci n'est que délicat dans la mesure où il n'y a rien de spécial à ce sujet. La version non surchargée nécessite un objet de type pointeur vers classe sur le côté gauche et un objet pointeur vers type membre sur la droite. Mais lorsque vous le surchargez, vous pouvez prendre tous les arguments que vous aimez et renvoyer tout ce que vous voulez. Il n'est même pas nécessaire que ce soit un membre non statique.
En d' autres termes, celui - ci est juste un opérateur binaire normal comme
+
,-
et/
. Voir aussi: Les opérateurs libres -> * surchargent-ils le mal?.*
et.
Ceux-ci ne peuvent pas être surchargés. Il existe déjà une signification intégrée lorsque le côté gauche est de type classe. Il serait peut-être un peu logique de pouvoir les définir pour un pointeur sur le côté gauche, mais le comité de conception du langage a décidé que ce serait plus déroutant qu'utile.
Surcharge
->
,->*
,.
et.*
ne peut remplir dans les cas où une expression serait indéterminée, il ne peut jamais changer le sens d'une expression qui serait valable sans surcharge.la source
new
opérateur, même s'il est valide même s'il n'est pas surchargé.new
est toujours surchargé, ou les règles de surcharge ne s'y appliquent pas vraiment (13.5 / 5: Les fonctions d'allocation et de désallocation, opérateur new, opérateur new [], opérateur delete et opérateur delete [], sont décrites en détail en 3.7 .4. les attributs et les restrictions trouvées dans le reste du présent paragraphe ne sont pas applicables à eux , sauf si explicitement indiqué dans 3.7.4.) Mais la surcharge unaire&
ou binaire&&
,||
ou,
, ou en ajoutant des surchargesoperator=
ou une surcharge à peu près tout pour une portée définie type d'énumération, peut changer la signification d'une expression. Clarifié la déclaration, merci!Opérateur -> est spécial.
"Il a des contraintes supplémentaires atypiques: il doit renvoyer un objet (ou une référence à un objet) qui a également un opérateur de déréférencement de pointeur, ou il doit renvoyer un pointeur qui peut être utilisé pour sélectionner sur quoi pointe la flèche de l'opérateur de déréférencement du pointeur. " Bruce Eckel: Thinking CPP Vol-one: opérateur->
La fonctionnalité supplémentaire est fournie pour plus de commodité, vous n'avez donc pas à appeler
Vous pouvez simplement faire:
Cela rend l'opérateur -> différent des autres surcharges d'opérateur.
la source
Vous ne pouvez pas surcharger l'accès des membres
.
(c'est-à-dire la deuxième partie de ce que->
fait). Vous pouvez toutefois surcharger le unaire déréférencement opérateur*
(la première partie de ce->
fait).L'
->
opérateur C ++ est fondamentalement l'union de deux étapes et c'est clair si vous pensez que celax->y
équivaut à(*x).y
. C ++ vous permet de personnaliser ce qu'il faut faire avec la(*x)
partie quandx
est une instance de votre classe.La sémantique pour la
->
surcharge est quelque peu étrange car C ++ vous permet soit de retourner un pointeur régulier (qu'il sera utilisé pour trouver l'objet pointé) soit de renvoyer une instance d'une autre classe si cette classe fournit également un->
opérateur. Lorsque dans ce second cas, la recherche de l'objet déréférencé se poursuit à partir de cette nouvelle instance.la source
->*
, car il est équivalent à la forme de(*x).*
?le
->
opérateur ne sait pas sur quel membre pointe le membre, il fournit simplement un objet sur lequel effectuer l'accès au membre réel.De plus, je ne vois aucune raison pour laquelle vous ne pouvez pas fournir de versions const et non const.
la source
Lorsque vous surchargez l'opérateur -> () (aucun argument n'est passé ici), ce que le compilateur fait réellement est d'appeler -> de manière récursive jusqu'à ce qu'il renvoie un pointeur réel vers un type. Il utilise ensuite le membre / méthode correct.
Ceci est utile, par exemple, pour créer une classe de pointeur intelligent qui encapsule le pointeur réel. L'opérateur surchargé-> est appelé, fait tout ce qu'il fait (par exemple le verrouillage pour la sécurité des threads), retourne le pointeur interne, puis le compilateur appelle -> pour ce pointeur interne.
En ce qui concerne constness - il a été répondu dans les commentaires et autres réponses (vous pouvez et devez fournir les deux).
la source