#pragma twice

KAB-studio > プログラミング > #pragma twice > 359 Version 17.04 アクセス修飾子のまとめ

#pragma twice 359 Version 17.04 アクセス修飾子のまとめ

前のページへ 表紙・目次へ 次のページへ

 Version 17.04
アクセス修飾子のまとめ

前回は protected について説明しました
派生クラスからアクセスできるのが protected 、できないのが private 、
全部OKが public ……ややこしー
そこで、今回は全部まとめてみます
おお
まず、メンバが〈どこからアクセスできるか〉を指定する public 、 
private 、 protected を【アクセス修飾子】とか【アクセス指定子】とい
います
あくせすしゅうしょくし、ね
これらを使用することで、メンバ変数やメンバ関数がどこから使えるのか
を指定することができます。表にすると、以下のようになります


■ public のアクセス範囲
○以下の箇所からアクセスできます。
・あらゆるメンバ関数
・あらゆる関数

○以下の箇所からはアクセスできません。
・アクセスできない箇所はありません


■ protected のアクセス範囲
○以下の箇所からアクセスできます。
・自クラスのメンバ関数
・派生クラスのメンバ関数

○以下の箇所からはアクセスできません。
・派生クラス以外の他クラスのメンバ関数
・通常の関数


■ private のアクセス範囲
○以下の箇所からアクセスできます。
・自クラスのメンバ関数

○以下の箇所からはアクセスできません。
・(派生クラスを含む)他クラスのメンバ関数
・通常の関数


次は図で見てみます。たとえば、以下のクラスがあるとします

// CData クラス。
class CData
{
public:
    int m_iPublic;
protected:
    int m_iProtected;
private:
    int m_iPrivate;
};

……そういえば、アクセス修飾子って、全部【 p 】から始まるんだね
だからちょっと紛らわしいかも……それは置いといて、アクセスできる
範囲を図にすると以下のようになります。以下の図は、

・CData クラスのメンバ関数
・CData クラスの派生クラスのメンバ関数
・まったく関係ないクラスのメンバ関数
・ただの関数

から、

CData クラスのメンバ変数
・m_iPublic
・m_iProtected
・m_iPrivate

にアクセスできるか、という図です。アクセスできたら○、できなかった
ら×です


┌──────────────┐
│   CData クラスの派生クラス │
│ ┌────────┐       │
│ │CData クラス    │       │
│ │                │       │
│ │ ○m_iPublic    │       │
│ │ ○m_iProtected │       │
│ │ ○m_iPrivate   │       │
│ └────────┘       │
│    ○m_iPublic             │
│    ○m_iProtected          │
│    ×m_iPrivate            │
└──────────────┘

┌──────────────┐
│   まったく関係ないクラス   │
│                            │
│  ○m_iPublic               │
│  ×m_iProtected            │
│  ×m_iPrivate              │
└──────────────┘

┌──────────────┐
│   ただの関数               │
│                            │
│  ○m_iPublic               │
│  ×m_iProtected            │
│  ×m_iPrivate              │
└──────────────┘


これだと一目瞭然ねー。 public はどこからでも、 private は自クラス
だけ、 protected はその中間、ってわけね
そういうこと
……で、具体的な使い分けってどうすればいいの? メンバ変数は 
private にするとか、メンバ関数は public にするとかはわかるけど
そうだね、使い分けは以下のような感じかな


■メンバ変数
・普通:
→ private

・派生クラスから使えるようにしたい場合:
→ protected


■メンバ関数
・外から呼び出す場合:
→ public

・派生クラスからのみ呼び出せるようにしたい場合:
→ protected

・自クラスでの処理専用:
→ private


むむむ、質問!
はい火美ちゃん
派生クラスから使うからメンバ変数を protected にする、っていうのは
イカンと思います!
だね、カプセル化の考えと反するからね
うんうん
これが許されるのは、基本クラスと派生クラスを一緒に作るような場合か

どゆこと?
基本クラスと派生クラスはあくまでペア。他の派生クラスを作ることや、
基本クラス単体で使うことを想定していなくて、基本クラスと派生クラスを
ひとつのクラスと考えるような場合、とか
ひとつのクラスだからメンバ変数に直接アクセスできてもいい、と
そういうこと。でも気になるのは重要だから、気になる場合にはメンバ変数
は private にしてアクセサ作って
それを派生クラスから呼び出せばいいわけね。そのアクセサを protected に
すればいい、と
そうすればメンバ変数のカプセル化は守られるからね。そっちの方が推奨
かも
んじゃそうする。メンバ関数は……こっちはいいかな
ただ、メンバ関数の方について注意点がふたつ。まず、 protected は限
りなく public に近い、と考えてください
ええっ? それって違くない? private に、派生クラスから使えるって
いうのが加わったのが protected じゃない
そうなんだけど、その許可がとても大きいんです。 private だと、
自クラス以外からは絶対にアクセスできません。たとえ派生クラスでも
うん、さっきの m_iPrivate メンバ変数も自クラス以外からは絶対に使え
なかったもんね
でも、それが protected になると話が違うんです
? 派生クラスからアクセスできるようになったってだけじゃん
それがとても大きいんです。前回の SetData() メンバ関数の例を思い出
して
んー、基本クラスの m_iData メンバ変数は protected で、派生クラスの
SetData() メンバ関数からはアクセスできた、けど外の WinMain() 関数か
らはアクセスできない、だよね
でも WinMain() は SetData() にはアクセスできるでしょ
そりゃ public だから……あ
つまり、 protected メンバにアクセスできる public なメンバ関数を
派生クラスで作っちゃうと、実質的に protected メンバが public メンバ
になっちゃう、ってことなんです


┌──────────────┐
│   CDerivedData             │
│ ┌────────┐       │
│ │CData           │       │
│ │                │       │
│ │m_iData ×←←←←←←←←←← WinMain()
│ │  ○            │       │        ↓
│ │  ↑            │       │        ↓
│ └─↑──────┘       │        ↓
│     ↑                     │        ↓
│   SetData()←←←←←←←←←←←←←←
└──────────────┘


こんな感じに、 WinMain() は直接 m_iData に値をセットできなくても、
SetData() メンバ関数を通せば間接的に値をセットできてしまうんです
つまり protected が public に……
派生クラスは自由に作れるから、たとえば……

・CData クラスの m_iData メンバ変数にアクセスできなくて不便だなぁ

・あ、 m_iData メンバ変数は protected だ

・CData クラスの派生クラス作っちゃおう

・そのクラスで m_iData の getter と setter を作っちゃおう

・そうしたら実質的に m_iData が外からアクセスできるように!

げげげげげ!
こういうことができちゃうのが protected 、できないのが private 。
この差はとても大きいってこと
だから protected は public に近い、ってわけね……

/*
    Preview Next Story!
*/
 protected は private 寄りじゃなくて public 似……むつかしい
シンタックスとセマンティクスの違いは難しいかもね
し、しんた……???
次回は分かりやすい CWnd クラスの話
あ、分かりやすそう
というわけで次回
< Version 17.05 CWnd クラスの継承関係 >
につづく!
分かりやすいのうれしい!  MFC 万歳!!
そ、そんなに!?
 
del.icio.us 登録する
Yahoo!ブックマーク 詳細を表示 users
livedoorクリップ 詳細を表示 livedoorクリップ ブックマーク数
はてなブックマーク 詳細を表示 はてなブックマーク ブックマーク数
RSSに登録
del.icio.us 登録する
Yahoo!ブックマーク 詳細を表示 users
livedoorクリップ 詳細を表示 livedoorクリップ ブックマーク数
はてなブックマーク 詳細を表示 はてなブックマーク ブックマーク数
 
このページは、Visual C++ 6.0を用いた C++ 言語プログラミングの解説を行う#pragma twiceの一コンテンツです。
詳しい説明は#pragma twiceのトップページをご覧ください。