Cpp クラス constのソースを表示
新しいページはコチラ
移動:
案内
,
検索
<table class="mbox-small" style="border:1px solid #aaa; background-color:#f9f9f9; width:22em;" id="RealTitleBanner"> <tr> <td style="width:1px;"></td> <td class="mbox-text plainlist" style="">本来の表記は「<b><span id="RealTitle" style="font-size:large;">C++ クラス const</span></b>」です。この記事に付けられた題名は{{記事名の制約}}から不正確なものとなっています。</td> </tr> </table> ※このページでは[[C PlusPlus|C++]]にのみ存在する機能として、記事タイトルが<nowiki>C++ クラス const</nowiki>になっています。<br /> <br /> == '''クラス const''' == クラスとconstキーワードの関係について、この項目で記述したいと思います。変数で使っていたconstキーワードとはまた違った使い方をしますが、基本的な理念は同じです。つまりは変数の中に格納した値を初期化や初期値から変更されないように定数化・保護するということを目的としています。変えられたくない。変えられると動かなくなる。とか、変えられても大丈夫なようにチェックするということから解放されたい。こういったプログラマの都合により使われるキーワードです。 constキーワードは大きなクラスや標準的に配布されるプログラムでも積極的に使われていますので、クラスに関連するところで、このキーワードが使われた時、どういった効力があって、何がどのていど保護されるのかを理解しておかないと、値を変更する手順の考え方の齟齬がクラス開発者とそれを利用する人の中で発生したり、クラス開発者自身の中でうまく、保護がかけられていない状態になったりします。 [[C キャスト|キャスト]]の記事でもconst外しの解説あたりで、ポインタの中身のconstとポインタ変数自身のconstについて紹介しましたが、ここでも改めてconstの基本について復習しておきます。 *'''定数変数の定義''' :const int nSize = 1000; :もしくは :int const nSize = 1000; *'''ポインタでの定数変数(アドレス差し替えによる中身の変更発生はOK)''' :const int* pnSize = &pnSize2; :もしくは :int const * pnSize = &pnSize2; const宣言されていないポインタ変数に上記のような方法で宣言された変数のアドレスを代入することもできません。その代入して移し替えたポインタ変数から中身が変更される可能性が生じるためです。 *'''アドレス変更できないポインタでの定数変数''' :const int * const pnSize = new int(1000); :もしくは :int const * const pnSize = new int(1000); となります。そしてキャストでは、このconst外しなる、奥の手があることも説明しました。つまり、constは保護したつもり程度の役割であって、完璧ではない。どうしても変更させないようにするには、自分でチェックするプログラムを組むのが良いかと思いますが、あまり根を詰めないほうがいいと思います。プログラムがどう使われるものなのかによって、その厳しさを変えていくくらいの態度でよいのだと感じます。 それではクラスにおけるconstにはどのようなものがあるのか見てみましょう。 クラスにおけるconstのだいたいのことがわかるサンプルを作ってみました。 CConst001.h <syntaxhighlight lang="cpp" line start="1"> #pragma once class CConst001 { private: const int m_constnValue; const int m_constnValue2; int m_nValue; public: const int mpub_constnValue; void mfpub_Set_m_nValue(int nPara1); void mfpub_Set_m_nValueConstPara(int nPara1); int mfpub_Get_m_nValue(); int mfpub_Get_m_nValue() const; int mfpubconst_Get_m_nValue() const; CConst001(void); ~CConst001(void); }; </syntaxhighlight> CConst001.cpp <syntaxhighlight lang="cpp" line start="1"> #include "stdafx.h" #include "Const001.h" void CConst001::mfpub_Set_m_nValue(int nPara1){ nPara1 = mpub_constnValue; m_nValue = 1000; printf("mfpub_Set_m_nValue\n", mpub_constnValue); printf("m_nValue =%d\n", m_nValue); printf("mpub_constnValue=%d\n", mpub_constnValue); } void CConst001::mfpub_Set_m_nValueConstPara(const int nPara1){ //nPara1 = mpub_nValue;★1.const付きの引数は関数内で変更できない。 m_nValue = 1000; printf("mfpub_Set_m_nValueConstPara\n", mpub_constnValue); printf("m_nValue =%d\n", m_nValue); printf("mpub_constnValue=%d\n", mpub_constnValue); } //★2.const付きのオブジェクトからは呼び出し不可能な関数 int CConst001::mfpub_Get_m_nValue(){ m_nValue = 10; return m_nValue; } //★3.const付きのオブジェクトからも呼び出し可能な関数 constメンバ関数 int CConst001::mfpubconst_Get_m_nValue() const{ //mpub_nValue = 10;★7.constメンバ関数ではメンバ変数の変更は出来ない。 return m_nValue; } //★4.constメンバ関数はオーバーロードできます。 int CConst001::mfpub_Get_m_nValue() const{ //mpub_nValue = 10;★7.constメンバ関数ではメンバ変数の変更は出来ない。 return m_nValue; } CConst001::CConst001(void):mpub_constnValue(0),m_constnValue(0),m_constnValue2(0)//★10.constメンバ変数の初期化 const以外も初期化できる。 { //mpub_constnValue = 100;★11.コンストラクタでもconstメンバ変数への代入はできない。 } CConst001::~CConst001(void) { } </syntaxhighlight> sample_main.cpp <syntaxhighlight lang="cpp" line start="1"> #include "stdafx.h" #include "Const001.h" int _tmain(int argc, _TCHAR* argv[]) { CConst001* CConst001_Instance = new CConst001;//★5. CConst001_Instance->mfpub_Set_m_nValue(1000); //CConst001_Instance->mpub_constnValue = 1000;★8.constメンバ変数の呼び出しは出来ない。 const CConst001* CConst001_constInstance = new CConst001;//★6. CConst001_constInstance->mfpubconst_Get_m_nValue(); CConst001_constInstance->mfpub_Get_m_nValue();//★9.constメンバ関数以外も呼び出せる。 return 0; } </syntaxhighlight> と、まずは長々とサンプルを貼りましたので、この時点でもう読み進めている人はあまりいないと思いますが、読み続けてくれている希少な読者のためにも説明はこの後に記載していきたいと思います。 他のサイトの解説の方がうまく説明されていると感じる人も多いと思います。読み終えた後に、このサイトで勉強してよかったと思えるくらいのメリットを…爪痕を残せればとは思っていますが…。所詮、趣味プログラマのたわごと。ぬかしよるわ。って感じでしょうか。ちなみにファイル名にxxxx001.cppとかいう数字のサフィックス(接尾句)がついていますが、これはですね。CConst.cppだと既に有名なクラスがあったりしたら嫌だなと思ってつけているだけでして、特に深い意味はありません。001が既に存在していたら002にすればいいだけなので、楽でしょ。で、バージョンをすっかりと差し替えたい場合とかに数字をあげたり、いろいろと使い道のあるサフィックスにしているつもりです。え?それだと、イチイチクラス名が長くなり過ぎだろ?あんたバカ!?みたいな意見もあるかと思いますが、変数やクラス名が長くなるのは、自分みたいな趣味プログラマは余裕で受け入れることができる度量があるわけです。なぜなら根をつめてプログラミングすることはあまりないので、たまのプログラミングで変数が長いくらいで疲れることはないので、読み返してわかりやすいことのほうが優先されています。数式の計算が長くなるときはコメントで何をやっているかを概要をいれたりします。とにかく、何の変数がどんな型になっているのかわかりやすくします。これが自己流です。でもいつもいつも長い訳ではありません。できるだけってだけです。疲れてるときやどうでもいいとき、あるいは単純プログラムや一夜漬けや連続作業時は、aとかbとか適当な変数を使うこともあります。 と、ここにきて、上記のような、どうでもいい説明を入れてみました。 ==引数== 4行目と12行目の関数では、メンバ関数の引数にconstがあるかないかの違いになっています。メンバ関数のプロトタイプ宣言(xxx.hファイルの方の記述)ではconstをつけてもつけなくても、効力はありません。 '''void CConst001::mfpub_Set_m_nValue(int nPara1){''' '''void CConst001::mfpub_Set_m_nValueConstPara(const int nPara1){''' ★1.部分のようにnPara1という引数の中身を関数の中で書き換えて利用するようなことがconst付きの方では出来なくなっています。もちろん呼び出す側の引数部分においては、constであろうとconstで無かろうと問題にはなりません。但し呼び出す側で既にconstになっているポインタ型変数や参照型変数をconstになっていない引数をうけとる関数を呼び出すことは違反です。中身が書き換わってしまう可能性があるからです。このあたりのやりとりに関する規則を具体的に理解するには、そのイメージを説明する絵があった方がわかりやすいのかもしれません。 ==constメンバ関数== ★2.★3.★4.の部分の内、★3.★4.のように関数名の最後にconstと記述するようなメンバ関数をconstメンバ関数と呼んでいます。メイン関数側の★6.部分のように呼び出し側のクラスオブジェクトそのものがすでにconstで定義されているか、どうかによって動作が変わる関数と考えていいと思います。★6.部分のようにconstで定義されている場合には★3.や★4.のようなconstメンバ関数として、メンバ関数内でメンバ変数を書き換えないことを保証した関数しか呼び出すことが出来ないオブジェクトになっています。★5.部分のようなconstで定義されていないオブジェクトであれば、★2.でも★3.でも★4.でも、つまりconstメンバ関数であっても、★9.部分のように、そうでなくても呼び出すことはできます。★2.と★4.のように同じ関数名でconstメンバ関数か、そうでない普通のメンバ関数かだけが違うような同名の関数を定義できます。同名の関数がある場合は、特にどちらを呼び出すかを指定しなくてもオブジェクトがconstであれば、constメンバ関数が選ばれて呼び出されます。通常のオブジェクトなら通常のメンバ変数が選ばれて呼び出されます。このように自動的に利用される関数が振り分けられる仕組みを利用し、同じ関数名で二つ目の関数を定義することを関数のオーバーロードと呼びます。 constにはconstを!constでなければconstでないものをという感じです。★8.部分のごとくです。 constメンバ関数がなければconstが定義されたオブジェクトからの呼び出しはエラーになります。もちろんconstメンバ関数内で★7.部分のようにメンバ変数を呼び出して、変数の中身を変更するような処理を記述することはできません。 プロトタイプ宣言(xxx.hファイル側の記述)をするときにもconstメンバ関数には、関数名の定義の後ろにconstのキーワードを記述する必要があります。 ==constメンバ変数== constが定義されたクラス内のメンバ変数をconstメンバ変数と呼ぶような決まりは特にないですが、constが定義されたメンバ変数はコンストラクタの記述によって初期化をしなければ、初期値を与えることができません。初期値を与えるには★10.部分の方法でしか初期値を与えることはできません。★11.部分のようにコンストラクタ内で代入するような形式でも駄目だし、ヘッダファイル側のメンバ変数宣言のところで初期値を代入することでも初期値を与えることはできません。 '''CConst001::CConst001(void):mpub_constnValue(0),m_constnValue(0),m_constnValue2(0)''' コンストラクタの関数の後に : を記述して、その後ろに引数を定義していきます。文字あるいは文字列のような一重引用符や二重引用符のリテラルを()の中に記述することもできます。この初期化は特にconstでないメンバ変数でなくても初期化できます。面倒ですが…。 長い文章になってしまいましたが、概ねの説明は完了です。
テンプレート:記事名の制約
(
ソースを閲覧
)
Cpp クラス const
に戻る。
個人用ツール
3.129.250.3
このIPアドレスのトーク
ログイン
名前空間
ページ
議論
変種
表示
閲覧
ソースを表示
履歴表示
操作
検索
案内
メインページ
コミュニティ・ポータル
最近の出来事
最近の更新
おまかせ表示
ヘルプ
ツールボックス
リンク元
関連ページの更新状況
特別ページ