Cpp クラス const 新しいページはコチラ
提供: yonewiki
(→const外し(const_cast)) |
|||
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++ クラス const</span></b>」です。この記事に付けられた題名は{{記事名の制約}}から不正確なものとなっています。</td> | + | <td class="mbox-text plainlist" style="">本来の表記は「<b><span id="RealTitle" style="font-size:large;">C++(Cpp) クラス const</span></b>」です。この記事に付けられた題名は{{記事名の制約}}から不正確なものとなっています。</td> |
</tr> | </tr> | ||
</table> | </table> | ||
8行: | 11行: | ||
<br /> | <br /> | ||
== '''クラス const''' == | == '''クラス const''' == | ||
+ | |||
クラスとconstキーワードの関係について、この項目で記述したいと思います。変数で使っていたconstキーワードとはまた違った使い方をしますが、基本的な理念は同じです。つまりは変数の中に格納した値を初期化や初期値から変更されないように定数化・保護するということを目的としています。変えられたくない。変えられると動かなくなる。とか、変えられても大丈夫なようにチェックするということから解放されたい。こういったプログラマの都合により使われるキーワードです。 | クラスとconstキーワードの関係について、この項目で記述したいと思います。変数で使っていたconstキーワードとはまた違った使い方をしますが、基本的な理念は同じです。つまりは変数の中に格納した値を初期化や初期値から変更されないように定数化・保護するということを目的としています。変えられたくない。変えられると動かなくなる。とか、変えられても大丈夫なようにチェックするということから解放されたい。こういったプログラマの都合により使われるキーワードです。 | ||
178行: | 182行: | ||
− | ==const外し(const_cast)== | + | ==const外し(const_cast) or const戻し== |
const_castを使うといろいろな場面でconstで指定されている変数(ポインタ変数やオブジェクトも含める)であったものをconst無しの扱いに変更が出来ます。それじゃ、constでは保護されないじゃん。なんじゃそりゃ。って思うやもしれませんが、constというものはそういうものです。では、どれくらいのことがやれるのか試してみましょう。 | const_castを使うといろいろな場面でconstで指定されている変数(ポインタ変数やオブジェクトも含める)であったものをconst無しの扱いに変更が出来ます。それじゃ、constでは保護されないじゃん。なんじゃそりゃ。って思うやもしれませんが、constというものはそういうものです。では、どれくらいのことがやれるのか試してみましょう。 | ||
− | + | ===constポインタ変数→通常メンバ関数のポインタ変数(参照変数)引数=== | |
+ | まず、メンバ関数の引数はconstではないのに、呼び出す側のプログラムではconstになってしまっている場合。これはメンバ関数を呼び出すときだけに限らず、通常のクラスではない関数の引数のときでも同じことなのですが、C++ではメンバ関数を多用しますので、基本的な作法として、一つ目の例としてもってきました。 | ||
例えばsample_main.cpp側で | 例えばsample_main.cpp側で | ||
273行: | 278行: | ||
− | ( | + | ===constメンバ関数内からメンバ関数呼び出し=== |
+ | constメンバ関数内から通常のメンバ関数を呼び出すことはできませんが、これもconst_castによって回避することができます。まずは、constメンバ関数内から通常のメンバ関数が呼び出せない動作について確かめるためのプログラムを作ってみます。 | ||
+ | |||
+ | |||
+ | サンプルは以下のとおりです。 | ||
+ | Const001.cpp(3つのメンバ関数の中身を変更しました。) | ||
+ | <syntaxhighlight lang="cpp" line start="1"> | ||
+ | … | ||
+ | 省略 | ||
+ | … | ||
+ | int CConst001::mfpubconst_Get_m_nValue() const{ | ||
+ | int nValue = mfpub_Get_m_nValue();//★30. | ||
+ | printf("■mfpubconst_Get_m_nValue() const\n"); | ||
+ | printf("nValue=%d\n",nValue); | ||
+ | return m_nValue; | ||
+ | } | ||
+ | |||
+ | |||
+ | int CConst001::mfpub_Get_m_nValue() { | ||
+ | printf("■mfpub_Get_m_nValue()\n"); | ||
+ | m_nValue = 10;★31. | ||
+ | return m_nValue; | ||
+ | } | ||
+ | |||
+ | //★32. | ||
+ | int CConst001::mfpub_Get_m_nValue() const{ | ||
+ | printf("■mfpub_Get_m_nValue() const\n"); | ||
+ | //m_nValue = 20;■constメンバ関数ではメンバ変数の変更は出来ない。 | ||
+ | return m_nValue; | ||
+ | } | ||
+ | … | ||
+ | 省略 | ||
+ | … | ||
+ | </syntaxhighlight> | ||
+ | ★30.部分でconstメンバ関数内から通常のメンバ関数を呼び出すようなつもりのプログラムを追記しました。 | ||
+ | |||
+ | |||
+ | それでsample_main.cppは変更せずに実行するとします。ちなみに、上記の変更について実際に呼び出しされる部分はこうでした。 | ||
+ | <syntaxhighlight lang="cpp" line start="1"> | ||
+ | … | ||
+ | 省略 | ||
+ | … | ||
+ | int _tmain(int argc, _TCHAR* argv[]) | ||
+ | { | ||
+ | … | ||
+ | 省略 | ||
+ | … | ||
+ | const CConst001* CConst001_constInstance = new CConst001; | ||
+ | CConst001_constInstance->mfpubconst_Get_m_nValue(); | ||
+ | … | ||
+ | 省略 | ||
+ | … | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | そうすると、実行してみると以下のように出力されます。 | ||
+ | |||
+ | 実行結果 | ||
+ | <syntaxhighlight lang="text"> | ||
+ | ■mfpubconst_Get_m_nValue() const | ||
+ | ■mfpub_Get_m_nValue() const | ||
+ | nValue=-842150451 | ||
+ | </syntaxhighlight> | ||
+ | という具合に、なります。★30.部分の記述では、動かないようなことを言っていたのに、あれ、呼び出せた?と一瞬思っちゃいますが、実はここでもconstにはconstを!の原理が働いています。 | ||
+ | |||
+ | |||
+ | '''int nValue = mfpub_Get_m_nValue();''' | ||
+ | |||
+ | |||
+ | もし、mfpub_Get_m_nValue()による呼び出しができているとしたら、★31.が実行されてnValueの値は10になっているはずですが、出力ではまったく違う値になっています。実は予め用意していた、もう一方の★32.のconstメンバ関数が実行されています。これはconstオブジェクトではconstメンバ関数しか呼べないということの復習になるでしょうか? | ||
+ | |||
+ | |||
+ | constメンバ関数が用意されていなければ、コンパイルエラーになります。 | ||
+ | |||
+ | |||
+ | で、★31が実行されるには、★30.の部分の呼び出しがconstではないオブジェクトから呼ばれたことにすればよいことになります。そのようにするには以下のように★30.部分を書き換えます。 | ||
+ | |||
+ | |||
+ | Const001.cpp | ||
+ | <syntaxhighlight lang="cpp" line start="1"> | ||
+ | … | ||
+ | 省略 | ||
+ | … | ||
+ | int CConst001::mfpubconst_Get_m_nValue() const{ | ||
+ | int nValue = const_cast<CConst001*>(this)->mfpub_Get_m_nValue();//★40. | ||
+ | printf("■mfpubconst_Get_m_nValue() const\n"); | ||
+ | printf("nValue=%d\n",nValue); | ||
+ | return m_nValue; | ||
+ | } | ||
+ | … | ||
+ | 省略 | ||
+ | … | ||
+ | </syntaxhighlight> | ||
+ | ★40.部分のようにconst_castによって、クラスのthisポインタ変数の型をconst CConst001*型→CConst001*型に変換するようにすると、実行結果は以下のように変わります。 | ||
+ | |||
+ | |||
+ | 実行結果 | ||
+ | <syntaxhighlight lang="text"> | ||
+ | ■mfpubconst_Get_m_nValue() const | ||
+ | ■mfpub_Get_m_nValue() | ||
+ | nValue=10 | ||
+ | </syntaxhighlight> | ||
+ | になります。 | ||
+ | |||
+ | |||
+ | '''const_cast<CConst001*>(this)->mfpub_Get_m_nValue();''' | ||
+ | |||
+ | は | ||
+ | |||
+ | '''const_cast<const CConst001*>(this)->mfpub_Get_m_nValue();''' | ||
+ | |||
+ | |||
+ | に変更すると、またconstオブジェクトに戻るので、実行結果も元に戻ります。thisポインタに関する理解がなければ、この項目のconst外しサンプルはイマイチわからないものに感じるかもしれません。thisポインタに関する理解があれば、他にも呼び出す方法はあると思いつく人もいるかもしれません。 | ||
+ | |||
+ | |||
+ | このことから、constとして生成されたオブジェクトからconstメンバ関数を呼ばれたときのメンバ関数内でのthisポインタの型はconst CConst001*のように constが付与されたポインタのように振る舞うことが分かります。 | ||
長い文章になってしまいましたが、概ねの説明は完了です。 | 長い文章になってしまいましたが、概ねの説明は完了です。 | ||
+ | |||
+ | |||
+ | [[C PlusPlus#C++からの技術|C++]]に戻る |