Cpp クラス アクセス指定子のソースを表示
新しいページはコチラ
移動:
案内
,
検索
<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++ クラス アクセス指定子</span></b>」です。この記事に付けられた題名は{{記事名の制約}}から不正確なものとなっています。</td> </tr> </table> ※このページでは[[C PlusPlus|C++]]にのみ存在する機能として、記事タイトルが<nowiki>C++ クラス アクセス指定子</nowiki>になっています。<br /> <br /> == '''クラス アクセス指定子''' == クラス宣言をするヘッダファイル側で指定するアクセス指定子は、クラスの利用時の基本的な制約を指定するものです。クラスとはじめて向き合った人は、なんのこっちゃわからんという感じになりやすい部分だと思います。クラスを利用するときの基本的な使い方を理解していないと、どうしても、このアクセス指定子の意味がわかり辛く感じるのだと思います。クラスの基本的な利用方法については既に[[Cpp クラス|クラス]]の項目に記述しましたので、軽く理解しておいたほうが良いと思います。クラスで行われる隠蔽の技術の解説についてもこの項目で長々と記述する予定です。まずは簡単な説明から記述します。 アクセス指定子には3種類のアクセスレベルが用意されています。 *public :クラスの外側からも呼び出しできる関数や変数になる。 *protected :クラス内部や派生されたクラスからも呼び出しできる関数や変数になる。publicとprivateの中間的なアクセスレベル。 *private :省略時の規定値。クラスの外側からは呼び出しできない関数や変数になる。つまり、クラス内部のみ呼び出しできるということ。 と簡単に説明しましたが、初めてクラスというものを使おうとする人にとっては、上記の簡単なまとめだけでは、まだしっくり来ないかもしれません。具体的に使ってみて理解しましょう。そして、クラスの内部とか外部とか、派生とかという表現の意味についても説明します。 C言語では、こんなのなかったんだから、覚えなくっても大丈夫ってわけには行かないのがアクセス指定子です。これを理解しないと、クラスを使うことはできないし、あやつることは出来ません。誰かが定義したクラスとかだと、うまくアクセス指定がされていて、クラス内のこの変数を変更すれば、プログラムの動作が変更されるのは、なんとなくわかるんだけど…変更しようとするとなんかコンパイルエラーが出まくって、使いこなせないイライラ!ってことになってしまいます。 この先の記述はだいたい、うっすらわかっている人にはまどろっこしい説明が続くかもしれませんが、半分くらい理解してる人でも、継承して派生させる場合にもアクセス指定子が使えるので、そのあたりの説明はもう少し先の方に記述しますので、派生時の一括定義に関するアクセス指定の件について理解していない人は、軽く下の方まで目をとおしておいた方が良いと思います。わかったつもりになるのが、プログラムを理解する上で一番危険なことです。あらゆる学問もそうだと思いますが… それでは、派生とか継承とか内部とか外部とか、意味の分からないキーワードを理解していくためにも具体的に使ってみます。以下は説明用の単純なサンプルクラスです。 Access_Specifiers001.h <syntaxhighlight lang="cpp" line start="1"> class CAccess_Specifiers001{ int m_nValue; //★1.メンバ変数 省略されている場合はprivate: public: //★2.この宣言からpublic: int mpub_nValue; void Set_m_nValue(int nSetValueP);//メンバ関数 int Get_m_nValue(); protected: //★3.この宣言からprotected: wchar_t m_wcUnit; void mf_m_nValue1000x(); void mf_m_nValuePermil(); private: //★4.明示的なprivate: int m_nManipulatorCnt; public: CAccess_Specifiers001(void); ~CAccess_Specifiers001(void); }; </syntaxhighlight> Access_Specifiers001.cpp <syntaxhighlight lang="cpp" line start="1"> #include "stdafx.h" #include "Access_Specifiers001.h" void CAccess_Specifiers001::Set_m_nValue(int nSetValueP){ m_nValue = nSetValueP; } int CAccess_Specifiers001::Get_m_nValue(){ return m_nValue; } void CAccess_Specifiers001::mf_m_nValue1000x(){ m_nValue = m_nValue * 1000; m_nManipulatorCnt++; } void CAccess_Specifiers001::mf_m_nValuePermil(){ m_nValue = m_nValue / 1000; m_nManipulatorCnt--; } CAccess_Specifiers001::CAccess_Specifiers001(void) { } CAccess_Specifiers001::~CAccess_Specifiers001(void) { } </syntaxhighlight> という具合のサンプルクラスを作ってみました。サンプルの割に長くなってしまいましたが、なんとなく1000倍したり1000分の1にしたりするだけの操作をするクラスです。今のところ欠陥だらけのクラスになっています。 まずはアクセス指定子の具体的な利用部分について説明しておきます。 ★1.部分のようにアクセス指定子を記述しないでクラスの中の定義を書き始めると、その部分はprivateを指定したのと同じ意味で変数や関数が定義されます。クラス内部からしか呼び出し出来ないという表現をしましたが、内部というキーワードについてはもう少し後での説明になります。変数名のプレフィックス(接頭語)としてm_をつけるのはクラスの使い方における基本的な変数命名法として定着しているものです。あとは自分独自の命名法になります。このWikiの記事を最初から全部読んでいる人には、管理人の独自の命名法について説明したと思いますので、それについては割愛します。変数名の付け方は自由です。ちょっとわかりにく日本語を使うなら任意(にんい)ともいいますね。 次に ★2.部分で具体的にアクセス指定子を明示した部分が登場します。 アクセス指定子''':''' のように:を使って終端を修飾します。この指定の後ろからアクセス指定の意味が変更されるということになります。ここではpublicを指定したので、この先で指定した関数や変数からは、クラスの外部からも呼び出し出来ることになります。外部というキーワードについても後程の説明になります。 そして ★3.部分には新たにprotectedのアクセス指定子を使いました。内部と継承で派生したクラスから呼び出せる変数や関数の定義になります。 最後に ★4.部分でprivateのアクセス指定子を使っています。またクラス内部だけの呼び出しが許される変数や関数の定義に切り替わります。このように何度でもアクセス指定子は使えます。繰り返し使えますが、通常はまとめて記述する人が多いです。何の設計図もなく、1000倍や1000分の1倍するような機能を持つクラスを作り、適当にアクセス指定子を割り振っていますので、この先、都合が悪くなるとアクセス指定子の設定を変更するかもしれません。今のところ、1000分の1にしたとき小数になるから、int型だけだと都合が悪くなりそうなことだけは気づいてますが、そのままにしています。あとでプログラムを変更することになるでしょう。 たったこれだけの説明で、これだけ長くなってしまいました。記事全体が相当長くなりそうな気配がぷんぷんとしてきました。基本中の基本のことがらをこれだけ冗長的に説明するのは体が持たないような気がしますし、読んでる人も疲れるから、あまり良い記事にはならない気がしますね。 '''ついてこれるヤツだけ、ついて来い!'''(なんつって、振り返ったら誰もついてきてない感じの風景が明確に想像できます。) メインプログラムや他のクラス内で以下のようにクラスを実際に利用するプログラムを記述すると以下のようになります。 sample_main.cpp <syntaxhighlight lang="cpp" line start="1"> #include "stdafx.h" #include "Access_Specifiers001.h" int _tmain(int argc, _TCHAR* argv[]) { printf("★アクセス指定子\n"); int nValue; CAccess_Specifiers001* CAccess_Specifiers001_Instance = new CAccess_Specifiers001; CAccess_Specifiers001_Instance->Set_m_nValue(120); nValue = CAccess_Specifiers001_Instance->Get_m_nValue(); printf("%d\n",nValue); return 0; } </syntaxhighlight> と上記のように利用します。_tmain関数からの呼び出し処理がいわゆる外部からの呼び出しにあたる処理になります。クラスを説明した記事でも記述しましたが、Access_Specifiers001.hファイルの★1.部分にあるようなm_nValueというint型の変数にはprivateというアクセス指定がなされていて、内部からの呼び出しだけが許されています。したがって、_tmain関数から呼び出すことはできないため、CAccess_Specifiers001_Instance->m_nValueのように変数の呼び出しをしようとするとコンパイルエラーになります。値を設定するにはSet_m_nValue関数を値を取得するにはGet_m_nValue関数を使うしかないのがCAccess_Specifiers001の取り決めになります。 これは何のために、こんなまどろっこしいことになっているのでしょうか?今のところのプログラムでは直接、m_nValueの値を設定できた方が良さそうに感じます。実はこのクラスはm_nValueには-999~999の値を最初に設定してほしいという規制を作りたいとします。そうするとSet関数内でその新たに規制のための処理を追加すれば良くて、直接に変数を呼び出して値を設定をすることはできないということが、クラスという機能を使う考え方になっています。そのためにアクセス指定子によって、直接に変数を呼び出すことを制御できることになります。このような仕組みを隠蔽と呼んでいます。英語だと確かインヘリタンスとかって呼ばれています。 クラスのメンバ関数もメンバ変数と同じで、呼び出されるとまずい関数を作りたくなったりする場合が生じてきます。では、実際にサンプルプログラムのAccess_Specifiers001.cppの内容を書き換えて、設定値に関する規制を作ろうと思います。以下のようになります。 Access_Specifiers001.cpp <syntaxhighlight lang="cpp" line start="1"> … 省略 … void CAccess_Specifiers001::Set_m_nValue(int nSetValueP){ if(m_nValue <= -1000 && m_nValue >=1000){ printf("Warning:Set_m_nValue関数で認められない値が設定されました。(Limit -999~999)\n"); } else{ m_nValue = nSetValueP; } } … 省略 … </syntaxhighlight> ちょっと冷たいエラーメッセージですが、とりあえず規制されました。Windowsとかのダイアログでの入力だと入れようとするとOKボタンが押せないとか、そういう感じの冷たさのエラーがでるのと同じです。親切ならOKボタンを押したときに、エラー値が入れられた値の欄を明示して、どの値がダメとか丁寧なエラーを出したり、入力したとたんエラーをしめすような、入力欄の名前の部分や、値そのものが赤色の文字になって不正であることを示したりします。ここでは、当初の目標であるアクセス指定子を出来るだけ丁寧に説明するというだけのサンプルであるという雑さをもちあわせたまま、無理やりにサンプルを作ります。 ク、クラス恐るべしだな。ひとつの機能の塊をもつのがクラスだから、こんな指定があるので、覚えるしかないですが、最初にこの技術をしったとき、こういった説明を読んでも尚、まだ納得してませんでした。ややこしい仕組みだなぁ。こんなのつかわなくてもプログラムなんてやれると反抗的な態度だった若かりし頃の自分を思い出します。最近の若い人はどんな風に感じるんだろうか。ICT社会だから、すぐ納得できるんだろうか。心配です。 とにもかくにもクラスの中で定義されてるメンバ関数から呼び出すのが内部(Access_Specifiers001.cpp内で記述している関数)で、それ以外は外部(上の例なら_tmain関数)ってことです。それが内部と外部です。わかっていただけていたら幸せなことです。 じゃ、あとはprotectedで説明した派生したクラスと内部だけっていうパターンを説明する感じですね。これは別の項目でも継承って奴について記述するつもりなので詳細は継承の記事を読んでもらえるといいんですけど、まずは簡単に派生ってやつのパターンを示したいと思います。でも、今日はここまでかな。
テンプレート:記事名の制約
(
ソースを閲覧
)
Cpp クラス アクセス指定子
に戻る。
個人用ツール
18.191.251.36
このIPアドレスのトーク
ログイン
名前空間
ページ
議論
変種
表示
閲覧
ソースを表示
履歴表示
操作
検索
案内
メインページ
コミュニティ・ポータル
最近の出来事
最近の更新
おまかせ表示
ヘルプ
ツールボックス
リンク元
関連ページの更新状況
特別ページ