C++ の「this」ポインタ
「this」ポインタを理解するには、オブジェクトがクラスの関数とデータ メンバーをどのように見ているかを知ることが重要です。
- 各オブジェクトはデータ メンバーの独自のコピーを取得します。
- コードセグメントに存在するのと同じ関数定義にオールアクセスします。
つまり、各オブジェクトはデータ メンバーの独自のコピーを取得し、すべてのオブジェクトはメンバー関数の単一のコピーを共有します。
それでは、各メンバー関数のコピーが 1 つだけ存在し、複数のオブジェクトによって使用されている場合、適切なデータ メンバーはどのようにアクセスされ、更新されるのでしょうか?
コンパイラは、関数の名前とともに暗黙的なポインタを「this」として提供します。
「this」ポインターは、すべての非静的メンバー関数呼び出しに隠し引数として渡され、すべての非静的関数の本体内でローカル変数として使用できます。 静的メンバー関数はオブジェクトなし (クラス名付き) で呼び出すことができるため、「this」ポインターは静的メンバー関数では使用できません。
クラス X の場合、このポインターの型は「X*」です。また、X のメンバー関数が const として宣言されている場合、このポインターの型は「const X *」になります (この GFact を参照)
C++ の初期のバージョンでは、「this」ポインタを変更できました。そうすることで、プログラマはメソッドが処理しているオブジェクトを変更できます。この機能は最終的に削除され、C++ では r 値になりました。
C++ では、次のコードを呼び出すことでオブジェクト自体を破棄できます。
delete> this> ;> |
Stroustrup 氏が述べたように、「this」はポインターではなく参照である可能性がありますが、参照は C++ の初期バージョンには存在しませんでした。 「this」が参照として実装されていれば、上記の問題を回避でき、ポインタよりも安全になる可能性があります。
「this」ポインタが使用される状況は次のとおりです。
1) ローカル変数名がメンバー名と同じ場合
#include> using> namespace> std;> > /* local variable is same as a member's name */> class> Test> {> private> :> > int> x;> public> :> > void> setX (> int> x)> > {> > // The 'this' pointer is used to retrieve the object's x> > // hidden by the local variable 'x'> > this> ->x = x;>> > }> > void> print() { cout < <> 'x = '> < < x < < endl; }> };> > int> main()> {> > Test obj;> > int> x = 20;> > obj.setX(x);> > obj.print();> > return> 0;> }> |
出力:
x = 20
コンストラクターにとっては、 初期化子リスト パラメータ名がメンバー名と同じ場合にも使用できます。
2) 呼び出し元のオブジェクトへの参照を返すには
/* Reference to the calling object can be returned */> Test& Test::func ()> {> > // Some processing> > return> *> this> ;> }> |
ローカル オブジェクトへの参照が返されると、返された参照は次の目的で使用できます。 関数呼び出しを連鎖させる 単一のオブジェクト上で。
#include> using> namespace> std;> > class> Test> {> private> :> > int> x;> > int> y;> public> :> > Test(> int> x = 0,> int> y = 0) {> this> ->x = x;>> this> ->y = y; }>> > Test &setX(> int> a) { x = a;> return> *> this> ; }> > Test &setY(> int> b) { y = b;> return> *> this> ; }> > void> print() { cout < <> 'x = '> < < x < <> ' y = '> < < y < < endl; }> };> > int> main()> {> > Test obj1(5, 5);> > > // Chained function calls. All calls modify the same object> > // as the same object is returned by reference> > obj1.setX(10).setY(20);> > > obj1.print();> > return> 0;> }> |
出力:
x = 10 y = 20
エクササイズ:
以下のプログラムの出力を予測します。コンパイル エラーがある場合は、修正します。
質問1
#include> using> namespace> std;> > class> Test> {> private> :> > int> x;> public> :> > Test(> int> x = 0) {> this> ->x = x; }>> > void> change(Test *t) {> this> = t; }> > void> print() { cout < <> 'x = '> < < x < < endl; }> };> > int> main()> {> > Test obj(5);> > Test *ptr => new> Test (10);> > obj.change(ptr);> > obj.print();> > return> 0;> }> |
質問2
#include> using> namespace> std;> > class> Test> {> private> :> > int> x;> > int> y;> public> :> > Test(> int> x = 0,> int> y = 0) {> this> ->x = x;>> this> ->y = y; }>> > static> void> fun1() { cout < <> 'Inside fun1()'> ; }> > static> void> fun2() { cout < <> 'Inside fun2()'> ;> this> ->fun1(); }>> };> > int> main()> {> > Test obj;> > obj.fun2();> > return> 0;> }> |
質問3
#include> using> namespace> std;> > class> Test> {> private> :> > int> x;> > int> y;> public> :> > Test (> int> x = 0,> int> y = 0) {> this> ->x = x;>> this> ->y = y; }>> > Test setX(> int> a) { x = a;> return> *> this> ; }> > Test setY(> int> b) { y = b;> return> *> this> ; }> > void> print() { cout < <> 'x = '> < < x < <> ' y = '> < < y < < endl; }> };> > int> main()> {> > Test obj1;> > obj1.setX(10).setY(20);> > obj1.print();> > return> 0;> }> |
質問4
#include> using> namespace> std;> > class> Test> {> private> :> > int> x;> > int> y;> public> :> > Test(> int> x = 0,> int> y = 0) {> this> ->x = x;>> this> ->y = y; }>> > void> setX(> int> a) { x = a; }> > void> setY(> int> b) { y = b; }> > void> destroy() {> delete> this> ; }> > void> print() { cout < <> 'x = '> < < x < <> ' y = '> < < y < < endl; }> };> > int> main()> {> > Test obj;> > obj.destroy();> > obj.print();> > return> 0;> }> |