Bonjour,
Est-ce que vous auriez un exemple pertinent d'utilisation de *this?
Merci d'avance.
Version imprimable
Bonjour,
Est-ce que vous auriez un exemple pertinent d'utilisation de *this?
Merci d'avance.
si tu fais un accesseur qui retourne une référence de la classe
Code:
1
2
3
4
5 class Object { public: inline const Object & Get(void) { return *this; } };
Salut,
De manière générale, chaque fois que tu veux renvoyer une référence (constante ou non) sur l'objet en cours.
Si tu dois implémenter ton propre opérateur d'affectation ( Type & operator= (Type const &) ) est un cas des plus classique ;)
Sinon, la plupart des cas dans lesquels l'utilisation de this est réellement pertinente est reliée d'une manière ou d''une autre au paradigme générique et aux classes template ;)
Si dans ton constructeur tu dois initialiser des attributs qui nécessite une référence sur l'objet en cours :
C'est un cas d'utilisation assez courant.Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25 class A; class B { public: B(A& a): m_a(a) {} private: A& m_a; }; class A { public: A(): m_b(*this) {} private: B m_b; }; A a;
Merci beaucoup pour vos réponses.
Je n'ai pas bien saisi la réponse de germinolegrand.
Mais j'ai compris les autres réponses.
Il est parfois nécessaire de faire en sorte qu'une classe quelconque puisse être mise en relation avec l'instance d'un objet dont le type peut parfaitement être identique ou différent.
Lorsque la relation peut ne pas exister (par exemple la relation vers le "parent" dans une relation enfant-->parent), tu n'as pas d'autre choix que de recourir à un pointeur pour qu'un pointeur null puisse être considéré comme étant "l'absence de parent".
Dans d'autres circonstances (par exemple, le patron de conception décorateur), il est possible d'estimer que l'objet référencé doive d'office exister, sans doute parce que l'objet référençant n'aura jamais qu'une durée de vie au maximum plus courte que celle de l'objet référencé.
Le pointeur vers l'objet référencé peut donc être avantageusement remplacé par une référence, qui assure l'existence de l'objet, contrairement aux pointeurs.
Seulement, une référence doit être définie au moment de son instanciation. Un code proche de
sera refusé à cause de cette règle et devrait être modifié en quelque chose commeCode:
1
2
3
4
5
6 int main(){ int i; int & ref; ref = i; return 0; }
Le seule moyen d'y arriver passe par deux étapes:Code:
1
2
3
4
5 int main(){ int i; int & ref = i; return 0; }
Mais, pour ce faire, il faut pouvoir disposer d'une référence sur l'objet référencé!
- Transmettre l'objet référencé, sous la forme d'une référence, au constructeur de l'objet référençant
- utiliser la liste d'initialisation pour assigner l'objet référencé à la référence dans l'objet référençant.
Or, lorsque l'on est au niveau de l'objet référencé (décoré), l'objet en cours est identifié par le pointeur "this".
En transmettant "ce qui est pointé" par le pointeur this au constructeur du référençant (du décorateur), on transmet bel et bien une référence vers l'objet courent / décoré / référencé, et tout le monde est content :D
Un autre example:
Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29 class World { public: void register_foo( Foo& foo ); void unregister_foo( Foo& foo ); Foo* find_foo( FooId id ); }; class Foo // non-copyable non-movable { ///... World& m_world; public: Foo( World& world ) : m_world( world ) { m_world.register_foo( *this ); // now the world know about this instance } ~Foo() { m_world.unregister_foo( *this ); // now the world don't refer to this instance anymore } };
Euh, le passage de référence à pointeur n'est-t-il pas supposé être un anti-pattern?
Il me semblait que dans les règles d'usage et les connotations attachées aux références, passer une référence à une fonction autre qu'un constructeur implique que la fonction n'a pas vocation à "garder" une référence/pointeur vers l'objet après son exécution (et donc, que l'objet est libre de disparaître sans prévenir). Écrire register_foo( Foo& foo );, bien que légal, serait alors une mauvaise pratique.
Je ne vois pas pourquoi. Je n'ai jamais vu cette regle et elle me semble absurde. Ici la reference indique que seul un objet valide peut etre fournis. Il n'y a pas d'autres garantiee que celle ci. Ah si: on est garanti que la fonction ne va pas prendre le ownership et qu'elle compte quand meme modifier cette instance (ce qui signifie qu'il y a peu de chances qu'il y ai une copie - et si on voulais faire une copie, register_foo( Foo foo ); aurait ete meilleur).
Avec un pointeur, ca aurait suggere la meme chose sauf qu'on accepte un pointeur null. Apres, tu peux toujours avoir des regles maisons qui iraient dans le sens de ce que tu dis, mais dans ce cas ce n'est pas a mon gout disons. Je prefere que le code m'indique ce que je suis capable de faire avec la fonction plutot que les commentaires. Or si la fonction prends un pointeur mais n'accepte pas null, tu devras le dire dans les commentaires que tout le monde lira apres le crash (si tu as la chance que ca crash).
Comme le ownership n'est pas pris par la fonction, ce qui est evident a sa signature, alors c'est a l'utilisateur de faire en sorte que l'objet soit vivant suffisamment longtemps pour que la fonction marche, et comme il sagit d'un "register" ou autre nom ("add") qui indique un enregistrement (mais toujours sans ownership) alors l'utilisateur peut desenregistrer l'objet si sa duree de vie est supposee plus courte que celle de World.
Bref, c'est en realite la meme logique qu'avoir des references dans un constructeur au final.
Par contre, c'est le nom de la fonction qui suggere l'enregistrement associe au fait que c'est une reference non-const. Autrement dis on a pas d'autre moyen clair d'indiquer qu'on va prendre une reference/pointeur vers l'objet et qu'on va le garder. Si il etait question de shared_ptr j'auris utilise un weak_ptr et ca aurait alors ete tres clair.