キーワード this は、特定の型のポインターを識別します。
クラス A の x という名前のオブジェクトを作成し、クラス A には、
非静的メンバー関数 f() があるとします。
関数 x.f() を呼び出す場合、f() の本体にあるキーワード
this は、x のアドレスです。
this ポインターを宣言したり、またはそれへの割り当てを行うことはできません。
静的メンバー関数は、this ポインターを持ちません。
クラス型 X のメンバー関数に対する this ポインターの型は、X* const です。 メンバー関数が const 修飾子を用いて宣言されている場合、クラス X のそのメンバー関数に 対する this ポインターの型は、const X* const です。 メンバー関数が volatile 修飾子を用いて宣言されている場合、クラス X のそのメンバー関数に 対する this ポインターの型は、volatile X* const です。 例えば、コンパイラーは、次の表記を許可しません。
struct A { int a; int f() const { return a++; } };
コンパイラーは、関数 f() の本体で、ステートメント a++ を許可しません。 関数 f() では、this ポインターは、A* const 型です。 関数 f() は、this が指すオブジェクトの一部を変更しようとしています。
this ポインターは、すべての非静的メンバー関数呼び出しに隠れた引き数として渡され、すべての非静的関数本体の中の ローカル変数として使用することができます。
例えば、メンバー関数本体内で this ポインターを使用することによって、メンバー関数が呼び出される特定の クラス・オブジェクトを参照することができます。 以下の例で示すコードによって作成される出力は、a = 5 です。
#include <iostream> using namespace std; struct X { private: int a; public: void Set_a(int a) { // The 'this' pointer is used to retrieve 'xobj.a' // hidden by the automatic variable 'a' this->a = a; } void Print_a() { cout << "a = " << a << endl; } }; int main() { X xobj; int a = 5; xobj.Set_a(a); xobj.Print_a(); }
メンバー関数 Set_a() では、ステートメント this->a = a は、this ポインターを使用して、自動変数 a によって隠された xobj.a を検索します。
クラス・メンバー名が隠蔽されていない限り、クラス・メンバー名の使用は、this ポインターとクラス・メンバー・アクセス演算子 (->) を用いたクラス・メンバー名の使用と同じです。
以下のテーブルの最初の列は、this ポインターを指定しないで、クラス・メンバーを使用するコードの例を示しています。
2 番目の列にあるコードは、変数 THIS を使用して、最初の列で、その使用が隠蔽されている this ポインターを
シミュレートします。
this ポインターを使用しないコード | 等価のコード。隠蔽されている this ポインターをシミュレートする THIS 変数を使用。 |
---|---|
#include <string> #include <iostream> using namespace std; struct X { private: int len; char *ptr; public: int GetLen() { return len; } char * GetPtr() { return ptr; } X& Set(char *); X& Cat(char *); X& Copy(X&); void Print(); }; X& X::Set(char *pc) { len = strlen(pc); ptr = new char[len]; strcpy(ptr, pc); return *this; } X& X::Cat(char *pc) { len += strlen(pc); strcat(ptr,pc); return *this; } X& X::Copy(X& x) { Set(x.GetPtr()); return *this; } void X::Print() { cout << ptr << endl; } int main() { X xobj1; xobj1.Set("abcd") .Cat("efgh"); xobj1.Print(); X xobj2; xobj2.Copy(xobj1) .Cat("ijkl"); xobj2.Print(); } |
#include <string> #include <iostream> using namespace std; struct X { private: int len; char *ptr; public: int GetLen (X* const THIS) { return THIS->len; } char * GetPtr (X* const THIS) { return THIS->ptr; } X& Set(X* const, char *); X& Cat(X* const, char *); X& Copy(X* const, X&); void Print(X* const); }; X& X::Set(X* const THIS, char *pc) { THIS->len = strlen(pc); THIS->ptr = new char[THIS->len]; strcpy(THIS->ptr, pc); return *THIS; } X& X::Cat(X* const THIS, char *pc) { THIS->len += strlen(pc); strcat(THIS->ptr, pc); return *THIS; } X& X::Copy(X* const THIS, X& x) { THIS->Set(THIS, x.GetPtr(&x)); return *THIS; } void X::Print(X* const THIS) { cout << THIS->ptr << endl; } int main() { X xobj1; xobj1.Set(&xobj1 , "abcd") .Cat(&xobj1 , "efgh"); xobj1.Print(&xobj1); X xobj2; xobj2.Copy(&xobj2 , xobj1) .Cat(&xobj2 , "ijkl"); xobj2.Print(&xobj2); } |
両方の例は、以下の出力を作成します。
abcdefgh abcdefghijkl
関連参照