this ポインター

C++キーワード this は、特定の型のポインターを識別します。 クラス Ax という名前のオブジェクトを作成し、クラス 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

関連参照

IBM Copyright 2003