Cpp クラス thisポインタ 新しいページはコチラ
提供: yonewiki
(→クラス thisポインタ) |
|||
1行: | 1行: | ||
+ | [[C PlusPlus#C++からの技術|C++]]に戻る | ||
+ | |||
+ | |||
<table class="mbox-small" style="border:1px solid #aaa; background-color:#f9f9f9; width:22em;" id="RealTitleBanner"> | <table class="mbox-small" style="border:1px solid #aaa; background-color:#f9f9f9; width:22em;" id="RealTitleBanner"> | ||
<tr> | <tr> | ||
<td style="width:1px;"></td> | <td style="width:1px;"></td> | ||
− | <td class="mbox-text plainlist" style="">本来の表記は「<b><span id="RealTitle" style="font-size:large;">C++ クラス thisポインタ</span></b>」です。この記事に付けられた題名は{{記事名の制約}}から不正確なものとなっています。</td> | + | <td class="mbox-text plainlist" style="">本来の表記は「<b><span id="RealTitle" style="font-size:large;">C++(Cpp) クラス thisポインタ</span></b>」です。この記事に付けられた題名は{{記事名の制約}}から不正確なものとなっています。</td> |
</tr> | </tr> | ||
</table> | </table> | ||
8行: | 11行: | ||
<br /> | <br /> | ||
== '''クラス thisポインタ''' == | == '''クラス thisポインタ''' == | ||
+ | |||
thisポインタとは、自分自身を指し示すポインタだと言われており、初心者が聴くとなんとなくワケがわからない教えられ方をあちらこちらでされているように見受けます。自分自身?それって何だ? | thisポインタとは、自分自身を指し示すポインタだと言われており、初心者が聴くとなんとなくワケがわからない教えられ方をあちらこちらでされているように見受けます。自分自身?それって何だ? | ||
24行: | 28行: | ||
例えば、わかりやすい例で示せば、以下のような感じのプログラムを動かすことで自分自身という表現の意味を理解できるやもしれません。 | 例えば、わかりやすい例で示せば、以下のような感じのプログラムを動かすことで自分自身という表現の意味を理解できるやもしれません。 | ||
+ | |||
+ | |||
+ | ThisPointer001.h | ||
+ | <syntaxhighlight lang="cpp" line start="1"> | ||
+ | #pragma once | ||
+ | class CThisPointer001 | ||
+ | { | ||
+ | public: | ||
+ | CThisPointer001(void); | ||
+ | ~CThisPointer001(void); | ||
+ | }; | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | |||
+ | ThisPointer001.cpp | ||
+ | <syntaxhighlight lang="cpp" line start="1"> | ||
+ | #include "stdafx.h" | ||
+ | #include "ThisPointer001.h" | ||
+ | |||
+ | |||
+ | CThisPointer001::CThisPointer001(void) | ||
+ | { | ||
+ | printf("this Address =%08x\n",this);//★1.thisポインタのアドレス出力 | ||
+ | } | ||
+ | |||
+ | |||
+ | CThisPointer001::~CThisPointer001(void) | ||
+ | { | ||
+ | } | ||
+ | |||
+ | </syntaxhighlight> | ||
+ | |||
+ | Sample_Main.cpp | ||
+ | <syntaxhighlight lang="cpp" line start="1"> | ||
+ | #include "stdafx.h" | ||
+ | #include "ThisPointer001.h" | ||
+ | |||
+ | int _tmain(int argc, _TCHAR* argv[]) | ||
+ | { | ||
+ | CThisPointer001* CThisPointer001_Instance = new CThisPointer001; | ||
+ | printf("CThisPointer001_Instance Address=%08x\n",CThisPointer001_Instance);//★2.変数のアドレス出力 | ||
+ | |||
+ | return 0; | ||
+ | } | ||
+ | |||
+ | </syntaxhighlight> | ||
+ | またしても、サンプルが長くなってしまいましたが、辛抱強く試してみた人がいたとしたら、実行結果は以下のようになったでしょう。 | ||
+ | |||
+ | |||
+ | 出力結果 | ||
+ | <syntaxhighlight lang="text"> | ||
+ | this Address =00579108 | ||
+ | CThisPointer001_Instance Address=00579108 | ||
+ | </syntaxhighlight> | ||
+ | ★1.と★2.でthisポインタの出力と生成したクラスオブジェクトの変数のアドレスが一致しました。これが自分自身ということの意味になります。だから?何ができるのか? | ||
+ | |||
+ | |||
+ | 例えば、thisポインタを使って、メンバ関数やメンバ変数を呼び出すことができます。でも、thisポインタを使わなくても呼び出せていました。そしたらthisポインタってのは何の役に立つのか?それはですね。自分自身の中の何かのメンバ変数やメンバ関数であることを明示しなければならない場合があるということにつきます。たとえば[[Cpp クラス メンバ関数ポインタ|メンバ関数ポインタ]]で明示しなければならないパターンを示しました。 | ||
+ | |||
+ | |||
+ | 自動的に作られるthisというキーワードのポインタ変数は、意図的にthisポインタと同じものを作ることができます。 | ||
+ | |||
+ | |||
+ | thisポインタと同じようなものを作るという意味で、プログラムを継ぎ足し変更したりして、以下のように変えてみます。 | ||
+ | |||
+ | |||
+ | ThisPointer001.h | ||
+ | <syntaxhighlight lang="cpp" line start="1"> | ||
+ | #pragma once | ||
+ | class CThisPointer001 | ||
+ | { | ||
+ | public: | ||
+ | int mpub_nValue;//★1 | ||
+ | CThisPointer001* this2;//★2 | ||
+ | void mfpub_SetThis(CThisPointer001* pCThisPointer001_this);//★3 | ||
+ | void mfpub_Output1(void);//★4 | ||
+ | |||
+ | CThisPointer001(void); | ||
+ | ~CThisPointer001(void); | ||
+ | }; | ||
+ | |||
+ | </syntaxhighlight> | ||
+ | ThisPointer001.cpp | ||
+ | <syntaxhighlight lang="cpp" line start="1"> | ||
+ | #include "stdafx.h" | ||
+ | #include "ThisPointer001.h" | ||
+ | |||
+ | //★5 | ||
+ | void CThisPointer001::mfpub_SetThis(CThisPointer001* pCThisPointer001_this){ | ||
+ | printf("\n"); | ||
+ | printf("■CThisPointer001::mfpub_SetThis\n"); | ||
+ | |||
+ | printf("pCThisPointer001_this Address =%08x\n",pCThisPointer001_this); | ||
+ | this2 = pCThisPointer001_this; | ||
+ | printf("this Address =%08x\n",this); | ||
+ | printf("this2 Address =%08x\n",this2); | ||
+ | |||
+ | pCThisPointer001_this->mpub_nValue = 10;//★10. | ||
+ | printf("mpub_nValue =%08d\n",mpub_nValue); | ||
+ | |||
+ | this->mpub_nValue = 100;//★11. | ||
+ | printf("mpub_nValue =%08d\n",mpub_nValue); | ||
+ | |||
+ | mpub_nValue = 2000;//★12. | ||
+ | printf("mpub_nValue =%08d\n",mpub_nValue); | ||
+ | |||
+ | } | ||
+ | |||
+ | //★6 | ||
+ | void CThisPointer001::mfpub_Output1(){ | ||
+ | printf("\n"); | ||
+ | printf("■CThisPointer001::mfpub_Output1\n"); | ||
+ | |||
+ | printf("this Address =%08x\n",this); | ||
+ | printf("this2 Address =%08x\n",this2); | ||
+ | printf("mpub_nValue =%08d\n",mpub_nValue); | ||
+ | |||
+ | } | ||
+ | |||
+ | CThisPointer001::CThisPointer001(void) | ||
+ | { | ||
+ | printf("\n"); | ||
+ | printf("■CThisPointer001コンストラクタ\n"); | ||
+ | printf("this Address =%08x\n",this); | ||
+ | } | ||
+ | |||
+ | |||
+ | CThisPointer001::~CThisPointer001(void) | ||
+ | { | ||
+ | } | ||
+ | |||
+ | </syntaxhighlight> | ||
+ | Sample_main.cpp | ||
+ | <syntaxhighlight lang="cpp" line start="1"> | ||
+ | #include "stdafx.h" | ||
+ | #include "ThisPointer001.h" | ||
+ | |||
+ | int _tmain(int argc, _TCHAR* argv[]) | ||
+ | { | ||
+ | CThisPointer001* CThisPointer001_Instance = new CThisPointer001; | ||
+ | |||
+ | CThisPointer001_Instance->mfpub_SetThis(CThisPointer001_Instance);//★100 | ||
+ | CThisPointer001_Instance->mfpub_Output1(); | ||
+ | |||
+ | CThisPointer001_Instance->mpub_nValue = 1000; | ||
+ | |||
+ | printf("\n"); | ||
+ | printf("■Main\n"); | ||
+ | printf("CThisPointer001_Instance Address=%08x\n",CThisPointer001_Instance); | ||
+ | |||
+ | return 0; | ||
+ | } | ||
+ | |||
+ | </syntaxhighlight> | ||
+ | そうすると、出力結果は以下のようになります。 | ||
+ | <syntaxhighlight lang="text"> | ||
+ | ■CThisPointer001コンストラクタ | ||
+ | this Address =0094eeb8 | ||
+ | |||
+ | ■CThisPointer001::mfpub_SetThis | ||
+ | pCThisPointer001_this Address =0094eeb8 | ||
+ | this Address =0094eeb8 | ||
+ | this2 Address =0094eeb8 | ||
+ | mpub_nValue =00000010 | ||
+ | mpub_nValue =00000100 | ||
+ | mpub_nValue =00002000 | ||
+ | |||
+ | ■CThisPointer001::mfpub_Output1 | ||
+ | this Address =0094eeb8 | ||
+ | this2 Address =0094eeb8 | ||
+ | mpub_nValue =00002000 | ||
+ | |||
+ | ■Main | ||
+ | CThisPointer001_Instance Address=0094eeb8 | ||
+ | </syntaxhighlight> | ||
+ | という具合です。 | ||
+ | |||
+ | |||
+ | 具体的に変更したところの中で重要なところはThisPointer001.hファイルの★1~★4を追加したこと、★5と★6のメンバ関数をプログラムとして追加したことです。 | ||
+ | |||
+ | |||
+ | そして、特に確認しておきたいのは★5の関数の引数として、CThisPointer001クラスのメンバ関数の引数として、CThisPointer001クラスのポインタ変数を受け取ることになっている点です。このように自分で自分を受け取るみたいな形でポインタ変数を引数とすることにより、まさにthisポインタと同じようなものを作ったことになります。もちろん、呼び出すときにはメインプログラム側で、実体のある自分自身を引数に受け取らないと、自分自身を示すポインタは作れないので、メインプログラム側の★100のように自分自身を引数にするような組み込みが要求されます。 | ||
+ | |||
+ | |||
+ | そうすると、★10のように | ||
+ | |||
+ | |||
+ | pCThisPointer001_this->mpub_nValue = 10; | ||
+ | |||
+ | |||
+ | というような★100で自分自身を受け渡したポインタ変数の中のメンバ変数への代入ができます。クラス内部からのアクセスなので、この代入はプライベートな領域のメンバ変数であっても呼び出すことが出来ます。その確認は自分自身にお任せしたいと思います。 | ||
+ | |||
+ | |||
+ | これが自分自身ということになります。★11では、あえてthisポインタを明示したメンバ変数へのアクセス方法を記述しました。★10と同じことをしているというのは、最初のサンプルプログラムで、同じアドレスを保持していたことからも理解してもらえるものと思います。 | ||
+ | |||
+ | |||
+ | ★12は従来というか、特に意識しなくても自分自身のメンバ変数にアクセスできていることがわかる部分になっています。 | ||
+ | |||
+ | |||
+ | thisはポインタと同じようなものを作ったと書きましたが、やはり★12のように省略してもいいし、いつでもthisポインタは使えるという点では、全く同じものを作ることはできません。thisポインタはいつでも使えるという点においては、C++の仕様ですから、この便利さにかなうものもなければ、これと同じ役割のキーワードを新たに作ることも難しいでしょう。常にthisと同じ役割をする別名の変数を作るように動作させるマクロとか作れるのかもしれませんが、それができるかどうかについても自分自身で確かめていただければと思います。それが必要かどうか答えは自分自身で見つけて。 | ||
+ | |||
+ | |||
+ | thisポインタが省略できるクラス内でのメンバ関数やメンバ変数の仕組みとかの原理や論理もあると思いますが、そのあたりは自分は理解していません。thisポインタの役割がわかっていれば、プログラムを読み解くことはできると思います。原理や論理を理解しないなんてバカだなぁと思う人はいるかもしれませんが、そういう人と関わるようになったときには積極的に理解していきたいと思います。そのときは優しく教えてくれるといいなぁ。この記事を読まれた若きプログラマは熱意をもって原理や論理にまで追求というか迫ると言うか、そういうようなことをしてもらったほうがいいのかもしれません。 | ||
+ | |||
+ | |||
+ | [[C PlusPlus#C++からの技術|C++]]に戻る |