Cette méthode ne fonctionne évidemment pas si la personne ne connaît pas la réponse.
Poser le
3
@JohnH .: Hm, on dirait que research.att.com/~bs/c'est maintenant stroustrup.com. Nouveau lien: stroustrup.com/bs_faq2.html#this
GManNickG
Réponses:
118
Habituellement, vous n'êtes pas obligé, this->est implicite.
Parfois, il y a une ambiguïté de nom, où il peut être utilisé pour lever l'ambiguïté des membres de classe et des variables locales. Cependant, voici un cas complètement différent où this->est explicitement requis.
Considérez le code suivant:
template<class T>struct A {int i;};template<class T>struct B : A<T>{int foo(){returnthis->i;}};int main(){
B<int> b;
b.foo();}
Si vous omettez this->, le compilateur ne sait pas comment traiter i, car il peut exister ou non dans toutes les instanciations de A. Pour lui dire qu'il iest effectivement membre de A<T>, pour tout T, le this->préfixe est requis.
Remarque: il est possible de toujours omettre le this->préfixe en utilisant:
template<class T>struct B : A<T>{using A<T>::i;// explicitly refer to a variable in the base classint foo(){return i;// i is now known to exist}};
Belle utilisation de la déclaration d'utilisation :)
Faisal Vali
3
C'est un cas particulièrement désagréable. J'ai déjà été mordu par ça.
Jason Baker le
5
C'est peut-être une question idiote, mais je ne comprends pas pourquoi cela ipourrait ne pas exister A. Puis-je avoir un exemple?
Cam Jackson
1
@CamJackson J'ai essayé le code sur Visual Studio. les résultats sont les mêmes, peu importe que "this->" existe ou non. Une idée?
Peng Zhang
8
@CamJackson: On peut spécialiser les classes sur le type:template<> struct A<float> { float x; };
Macke
31
Si vous déclarez une variable locale dans une méthode avec le même nom qu'un membre existant, vous devrez utiliser this-> var pour accéder au membre de classe au lieu de la variable locale.
#include<iostream>usingnamespace std;class A
{public:int a;void f(){
a =4;int a =5;
cout << a << endl;
cout <<this->a << endl;}};int main(){
A a;
a.f();}
Dans votre dernier cas, notez que vous pouvez appeler une constfonction non membre sur un temporaire ( Type(rhs).swap(*this);c'est légal et correct) mais un temporaire ne peut pas se lier à un paramètre de référence non-const (le compilateur rejette swap(Type(rhs));aussi bien que this->swap(Type(rhs));)
Ben Voigt
5
Il y a peu de cas où l'utilisation thisdoit être utilisée, et il y en a d'autres où l'utilisation du thispointeur est un moyen de résoudre un problème.
1) Alternatives disponibles : pour résoudre l'ambiguïté entre les variables locales et les membres de la classe, comme illustré par @ASk .
2) Aucune alternative: pour renvoyer un pointeur ou une référence à thisune fonction membre. Cela se fait souvent (et doit être fait) en cas de surcharge operator+, operator-, operator=, etc:
Certains considèrent cela comme une consise, d'autres le considèrent comme une abomination. Comptez-moi dans ce dernier groupe.
3) Aucune alternative: pour résoudre les noms dans les types dépendants. Cela se produit lors de l'utilisation de modèles, comme dans cet exemple:
#include<iostream>template<typenameVal>classValHolder{private:Val mVal;public:ValHolder(constVal& val):
mVal (val){}Val&GetVal(){return mVal;}};template<typenameVal>classValProcessor:publicValHolder<Val>{public:ValProcessor(constVal& val):ValHolder<Val>(val){}ValComputeValue(){// int ret = 2 * GetVal(); // ERROR: No member 'GetVal'int ret =4*this->GetVal();// OK -- this tells compiler to examine dependant type (ValHolder)return ret;}};int main(){ValProcessor<int> proc (42);constint val = proc.ComputeValue();
std::cout << val <<"\n";}
4) Alternatives disponibles: dans le cadre du style de codage, pour documenter les variables qui sont des variables membres par opposition aux variables locales. Je préfère un schéma de dénomination différent où les varibales des membres ne peuvent jamais avoir le même nom que les locaux. Actuellement, j'utilise mNamepour les membres et namepour les locaux.
Vous ne devez utiliser this-> que si vous avez un symbole avec le même nom dans deux espaces de noms potentiels. Prends pour exemple:
class A {public:void setMyVar(int);void doStuff();private:int myVar;}void A::setMyVar(int myVar){this->myVar = myVar;// <- Interesting point in the code}void A::doStuff(){int myVar =::calculateSomething();this->myVar = myVar;// <- Interesting point in the code}
Aux points intéressants du code, faire référence à myVar fera référence au local (paramètre ou variable) myVar. Afin d'accéder au membre de classe également appelé myVar, vous devez utiliser explicitement "this->".
C'est la seule utilisation this->qui est triviale à éviter (donnez simplement un nom différent à la variable locale). Toutes les utilisations vraiment intéressantes de thisne sont même pas mentionnées par cette réponse.
cmaster - réintégrer monica
4
Les autres utilisations de cela (comme je le pensais en lisant le résumé et la moitié de la question ....), Sans tenir compte de la (mauvaise) désambiguïsation de la dénomination dans les autres réponses, sont si vous souhaitez convertir l'objet actuel, liez-le dans un objet fonction ou utilisez-le avec un pointeur vers un membre.
Moulages
voidFoo::bar(){
misc_nonconst_stuff();constFoo* const_this =this;
const_this->bar();// calls const versiondynamic_cast<Bar*>(this)->bar();// calls specific virtual function in case of multi-inheritance}voidFoo::bar()const{}
Non, vous n'en avez pas besoin , vous pouvez l' utiliser . Vous pouvez également utiliser un nom différent pour l'argument de fonction, ce qui présente l'avantage de ne pas avoir deux entités avec le même nom.
cmaster
3
Le but principal (ou je peux dire, le seul) du thispointeur est qu'il pointe vers l'objet utilisé pour appeler une fonction membre.
Sur la base de cet objectif, nous pouvons avoir des cas où seule l'utilisation d'un thispointeur peut résoudre le problème.
Par exemple, nous devons renvoyer l'objet appelant dans une fonction membre avec l'argument est un même objet de classe:
class human {...
human & human::compare(human & h){if(condition)return h;// argument objectelsereturn*this;// invoking object}};
Ou vous pouvez rendre lengthmutable, ou même le mettre dans une structure imbriquée. Rejeter la constness n'est presque jamais une bonne idée.
Richard J.Ross III
3
Veuillez ne pas le faire. Si le membre doit être modifié à partir des constfonctions membres, il doit l'être mutable. Sinon, vous compliquez la vie pour vous et pour les autres responsables.
research.att.com/~bs/
c'est maintenantstroustrup.com
. Nouveau lien: stroustrup.com/bs_faq2.html#thisRéponses:
Habituellement, vous n'êtes pas obligé,
this->
est implicite.Parfois, il y a une ambiguïté de nom, où il peut être utilisé pour lever l'ambiguïté des membres de classe et des variables locales. Cependant, voici un cas complètement différent où
this->
est explicitement requis.Considérez le code suivant:
Si vous omettez
this->
, le compilateur ne sait pas comment traiteri
, car il peut exister ou non dans toutes les instanciations deA
. Pour lui dire qu'ili
est effectivement membre deA<T>
, pour toutT
, lethis->
préfixe est requis.Remarque: il est possible de toujours omettre le
this->
préfixe en utilisant:la source
i
pourrait ne pas existerA
. Puis-je avoir un exemple?template<> struct A<float> { float x; };
Si vous déclarez une variable locale dans une méthode avec le même nom qu'un membre existant, vous devrez utiliser this-> var pour accéder au membre de classe au lieu de la variable locale.
imprime:
5
4
la source
Il existe plusieurs raisons pour lesquelles vous devrez peut-être utiliser
this
explicitement le pointeur.la source
Bien que je n'aime généralement pas ça, j'ai vu d'autres utiliser ça-> simplement pour obtenir de l'aide d'intellisense!
la source
Certaines normes de codage utilisent l'approche (2) car elles prétendent qu'elle facilite la lecture du code.
Exemple:
Supposons que MyClass a une variable membre appelée 'count'
la source
Un autre cas est lors de l'appel d'opérateurs. Par exemple au lieu de
tu peux dire
Ce qui pourrait être plus lisible. Un autre exemple est le copy-and-swap:
Je ne sais pas pourquoi ce n'est pas écrit,
swap(temp)
mais cela semble être courant.la source
const
fonction non membre sur un temporaire (Type(rhs).swap(*this);
c'est légal et correct) mais un temporaire ne peut pas se lier à un paramètre de référence non-const (le compilateur rejetteswap(Type(rhs));
aussi bien quethis->swap(Type(rhs));
)Il y a peu de cas où l'utilisation
this
doit être utilisée, et il y en a d'autres où l'utilisation duthis
pointeur est un moyen de résoudre un problème.1) Alternatives disponibles : pour résoudre l'ambiguïté entre les variables locales et les membres de la classe, comme illustré par @ASk .
2) Aucune alternative: pour renvoyer un pointeur ou une référence à
this
une fonction membre. Cela se fait souvent (et doit être fait) en cas de surchargeoperator+
,operator-
,operator=
, etc:Cela permet un idiome appelé « chaînage de méthodes », dans lequel vous effectuez plusieurs opérations sur un objet dans une ligne de code. Tel que:
Certains considèrent cela comme une consise, d'autres le considèrent comme une abomination. Comptez-moi dans ce dernier groupe.
3) Aucune alternative: pour résoudre les noms dans les types dépendants. Cela se produit lors de l'utilisation de modèles, comme dans cet exemple:
4) Alternatives disponibles: dans le cadre du style de codage, pour documenter les variables qui sont des variables membres par opposition aux variables locales. Je préfère un schéma de dénomination différent où les varibales des membres ne peuvent jamais avoir le même nom que les locaux. Actuellement, j'utilise
mName
pour les membres etname
pour les locaux.la source
Vous ne devez utiliser this-> que si vous avez un symbole avec le même nom dans deux espaces de noms potentiels. Prends pour exemple:
Aux points intéressants du code, faire référence à myVar fera référence au local (paramètre ou variable) myVar. Afin d'accéder au membre de classe également appelé myVar, vous devez utiliser explicitement "this->".
la source
this->
qui est triviale à éviter (donnez simplement un nom différent à la variable locale). Toutes les utilisations vraiment intéressantes dethis
ne sont même pas mentionnées par cette réponse.Les autres utilisations de cela (comme je le pensais en lisant le résumé et la moitié de la question ....), Sans tenir compte de la (mauvaise) désambiguïsation de la dénomination dans les autres réponses, sont si vous souhaitez convertir l'objet actuel, liez-le dans un objet fonction ou utilisez-le avec un pointeur vers un membre.
Moulages
Contraignant
ptr-à-membre
J'espère que cela aidera à montrer d'autres utilisations de ceci que juste ce membre.
la source
Vous devez utiliser
this
pour lever l'ambiguïté entre un paramètre / des variables locales et des variables membres.la source
Le but principal (ou je peux dire, le seul) du
this
pointeur est qu'il pointe vers l'objet utilisé pour appeler une fonction membre.Sur la base de cet objectif, nous pouvons avoir des cas où seule l'utilisation d'un
this
pointeur peut résoudre le problème.Par exemple, nous devons renvoyer l'objet appelant dans une fonction membre avec l'argument est un même objet de classe:
la source
J'ai trouvé un autre cas intéressant d'utilisation explicite du pointeur «this» dans le livre Effective C ++.
Par exemple, disons que vous avez une fonction const comme
Vous ne voulez pas calculer la longueur de String pour chaque appel, vous voulez donc le mettre en cache en faisant quelque chose comme
Mais cela ne compilera pas - vous modifiez l'objet dans une fonction const.
L'astuce pour résoudre cela nécessite de convertir ceci en un non-const this :
Ensuite, vous pourrez faire ci-dessus
la source
length
mutable, ou même le mettre dans une structure imbriquée. Rejeter la constness n'est presque jamais une bonne idée.const
fonctions membres, il doit l'êtremutable
. Sinon, vous compliquez la vie pour vous et pour les autres responsables.