- 締切済み
内部クラスのスコープについて。
内部クラスのスコープ、friendクラスのスコープについて詳しいかたお願いします。 以下のクラス構成の場合に、 1.Outerクラスのすべてメンバー関数からはInnerクラスのすべての関数にアクセスできるのでしょうか? 2.InnerクラスからOuter::outerPrivateFunction(); を利用するためにはInnerクラスをOuterクラスのfriendにする方法以外にありますでしょうか? 3.InnerクラスからOuter::outerInt にどのようにしてもアクセスできません。ためした方法はInnerクラスをOuterクラスのfriendにする方法です。 このようなクラス構成にしてしまうと不可能なのでしょうか? 4.friendにしたクラスはprivateの変数、関数にアクセス可能になるはずですが、 それは外部クラスに限ってのことで内部クラスには当てはまらないのでしょうか? class Outer { private: class Inner { Innerfunction(); Onter* pOuter; } outerPrivateFunction(); int outerInt; } 説明に不足があれば補足いたしますのでお詳しいかた宜しくお願いします。
- みんなの回答 (3)
- 専門家の回答
みんなの回答
- machongola
- ベストアンサー率60% (434/720)
こんばんは。再投稿です。 ↓すんません、仕出かしてしまいました。これはNGです。 void outerPrivateFunction() { Inner().Innerfunction(); } 以下問題点・御指摘頂いた点を修正してみました。VC6.0とVC2005でコンパイル、実行もしてあります。 どうやらOuter::が無くても良い(?)様です。 //friend class Innerを妨害するための独立したInnerクラス class Inner { void Innerfunction(){ } int a; int b; }; //本題のクラス class Outer { private: class Inner; friend class Inner; class Inner { private: friend Outer; public: explicit Inner(Outer* p) : pOuter(p){ } private: void Innerfunction() { pOuter->outerInt++; pOuter->outerPrivateFunction(); } void Innerfunction2(){ } Outer* pOuter; }; public: Outer() : inner(this), outerInt(0){ } void outerPublicFunction(){ inner.Innerfunction(); } private: void outerPrivateFunction(){ inner.Innerfunction2(); } Inner inner; int outerInt; }; 「More C++ Idioms/内部クラス(Inner Class)」 http://ja.wikibooks.org/wiki/More_C%2B%2B_Idioms/%E5%86%85%E9%83%A8%E3%82%AF%E3%83%A9%E3%82%B9(Inner_Class)
- redfox63
- ベストアンサー率71% (1325/1856)
Outer側のfriend宣言は friend class Outer::Inner; としてやれないといけないでしょう friend class Inner; と書いてしまっては class Outer { }; Class Inner { }; と独立したクラスだと解釈されるでしょう Innerfunctionは Outerの参照を引数にとるかInnerクラスのコンストラクタでpOuterを初期化するとかしないとpOuterの初期化ができないように思います OuterのouterPrivateFunctionやouterIntがprivateならInnerクラスに friend class Outer; が無いとエラーになるでしょう
お礼
細かいところまでフォローありがとうございます。
- machongola
- ベストアンサー率60% (434/720)
こんにちは。 1・はい。Innerクラスのメンバ関数へのアクセス指定をpublicにすれば可能です。 2・はい。ただ、するべき事では無いかと。 Outerクラスにstaticメンバ関数などを置き、その関数がOuter::outerPrivateFunction()のメンバ関数ポインタを返せば出来ます。 ただ、メンバ関数ポインタを返す関数は、publicでないと出来ません。 3・friendの書き方が悪かったのかもしれません。 4・可能な筈です。 以下で通る筈です(余白を空ける為に全角スペースを入れているので要注意)。 class Outer { private: class Inner; friend class Inner; class Inner { public: void Innerfunction() { pOuter->outerPrivateFunction(); pOuter->outerInt; } private: Outer* pOuter; }; void outerPrivateFunction() { Inner().Innerfunction(); } int outerInt; };
お礼
ありがとうございます。 確認したところ、ご指摘どおりfriendの書き方が悪く、 class Innerの仮定義をclass Outerの外に出しておりました。 内部クラスの場合には、内部で定義する必要があるのですね。 とても助かりました。
お礼
補足ありがとうございます。わざわざ動かしていただいたみたいで。 friend Outer;が少しはまりそうなので覚えておきます。 friend class Outer;としてしまいそうです。
補足
>どうやらOuter::が無くても良い(?)様です。 これですが必要ないと思います。 Interクラスの仮定義をOuterクラスの外に出すか、中に書くかで 外部クラス、内部クラスを指定することができるのではないでしょうか。 ですので、上記コードですと、class Innter;(仮定義)をコメントアウトすれば 、妨害するための独立したInnerクラスをfriendにすることができるのではないでしょうか。