- C++相談室 part124 [無断転載禁止]©2ch.net
968 :デフォルトの名無しさん (ワッチョイ 7b5b-xKv1)[sage]:2016/05/20(金) 19:36:46.02 ID:gU7EupTq0 - 質問です。
内部クラスから外側クラスのインスタンスメンバを参照したいのですが、 ググッた感じでは参照を渡すしかないっぽいのですが、これってマジですか? マジなら、面倒なので内部クラスのstaticに入れてしまおうかとも思っているのですが、これってありですか? (外部クラスが生成される度に内部クラスが別々に生成されて大丈夫なのか、 それとも内部クラスとして書いても外にフラットに書いても同じで、クラスで唯一のstatic変数となってバグりますか?) 或いはこの場合に一般的に使われるような手法はありますか? 参考コード:動かしていないので雰囲気だけ確認してください。 class OuterClass { class InnerClass { static OuterClass* parent; // <- これあり?それとも OuterClassを複数作成しても唯一になって駄目? void method_cpp0(int score){ parent->score += score; // <- こう使うつもり } void method_cpp1(int score, OuterClass* p) { // <- こうじゃないと駄目? p->score += score; } void method_javascript(int s){ score += s; // JavaScriptはこれができる。これができればうれしい。 } void method_java(int score){ OuterClass.this.score += score; // Java はこれができるらしい。これでもいい。 } }; int score; };
|
- C++相談室 part124 [無断転載禁止]©2ch.net
971 :デフォルトの名無しさん (ワッチョイ 7b5b-xKv1)[sage]:2016/05/20(金) 20:29:11.61 ID:gU7EupTq0 - >>970
コンストラクタでやるという記述もググッた時に見つかったのですが、 今回はInnerClassを一つではなく配列として持つので、メモリをケチろうかと。 コンストラクタで渡した方が確かに記述は綺麗なのですが。 とはいえ、改めて「プログラミング言語C++」を確認しても、 クラス継承の話は多くてもクラス内包の話がほぼ無いので、 一般的にはコンストラクタで「メンバ変数」として渡すのでしょうか。確かにこれだと確実です。 記述的にはコンストラクタ内でstaticに対して上書きしまくってもいいのですが、 これができるのか?というのは若干不安ですし。
|
- C++相談室 part124 [無断転載禁止]©2ch.net
973 :デフォルトの名無しさん (ワッチョイ 7b5b-xKv1)[sage]:2016/05/20(金) 20:56:18.27 ID:gU7EupTq0 - つまりstaticはどこに書いてあるクラスでも1つかもしれないと。
OuterClassは当面は1つで済みますが、今後複数化する可能性もあるので、シングルトンは駄目です。 余り真面目にC++やってなかったのですが、 内部クラスから外部クラスが階層アクセスできないのは、C++の仕様がちょっと古い気がします。 後発のJavaやJavaScriptは最初から出来るので。 ちなみに参考コード class OuterClass { class InnerClass { // 省略 }; int score; vector<InnerClass> nodes; };
|
- C++相談室 part124 [無断転載禁止]©2ch.net
983 :デフォルトの名無しさん (ワッチョイ 7b5b-xKv1)[sage]:2016/05/20(金) 22:43:44.89 ID:gU7EupTq0 - >>974
いや特にありません。そもそも非オブジェクト指向でも当然組めます。 ただ、色々試した結果、オブジェクト指向に慣れてくると、 Java的な「それ刻みすぎじゃねーの?」と思えるような所まで刻んだ方が 結果的に見やすかったり、後々融通が利くことが何となく分かってきました。 なので、今後はそうしようかと試しています。 >>975 詳細にありがとうございます。やはりstaticでは駄目ですか。 method_cpp1は今回は可能ですが、記述の抽象度が混ざるので出来ればクラス分けしたかったのです。 JavaやJavaScriptでもメモリ使用量が少ないわけではないのはその通りですが、 内部クラスからは外部クラスを参照するのはかなり普通のことなので、 これは言語として対応して欲しかったところです。今まで拡張されなかったのが不思議なくらいです。 これはコンパイラ側だけで完全に対応でき、実行時の追加コストはありません。 (不要ならコンパイル時点で外側クラスポインタの確保を止めることが出来る) 申し訳ありませんが、メモリ配置上の制約というのは何のことか分かりません。
|
- C++相談室 part124 [無断転載禁止]©2ch.net
984 :デフォルトの名無しさん (ワッチョイ 7b5b-xKv1)[sage]:2016/05/20(金) 22:44:35.94 ID:gU7EupTq0 - ちなみに、やろうとしていることに近く、イメージ的に分かりやすいのは、「ライフゲームをオブジェクト指向で」です。
参考コード、非オブジェクト指向 bool map[64][64]; bool map_next[64][64]; for (int i=0;i<64;i++) for (int j=0;j<64;j++) map_next[i][j] = life_exe(i,j); 参考コード、オブジェクト指向 class LifeGame { class Dot { int x, int y; void life_exe(){} // ここで外側の map, map_new に直接アクセスして更新させたい。 }; bool map[64][64]; bool map_next[64][64]; }; 実際にやろうとしていることは、正規表現の探索に近いです。 ライフゲームのように外側変数が時系列で変化するものではないため、 探索途中経過(Dot)をオブジェクトとして持ち、 最初から各オブジェクトに終わりまで探索(life_exe)させる事が出来ます。 とはいえ、やはりメリットは大してありませんが。
|
- C++相談室 part124 [無断転載禁止]©2ch.net
991 :デフォルトの名無しさん (ワッチョイ 7b5b-xKv1)[sage]:2016/05/20(金) 23:24:48.47 ID:gU7EupTq0 - >>986
インナーにするのは、DotはLifeGameでしか使わないからです。(他から見える必要がない) オブジェクト指向にするのは、多分制御が簡単になりそうだからなのと、 その際に記述が抽象階層で分離でき、見やすくなると予想されるからです。 もっと良い例がありました。「文書内の不完全マッチによる最有力候補探索」です。 これはほぼやりたいことと同じです。 例えばテキスト文書があったとして、「あいうえおかきくけこ」を探索するとします。 ここで、そのまま「あいうえおかきくけこ」があれば100点、それを示して終わりです。 これがない場合、欠け方それぞれで得点付けし、とにかく一番得点が高い候補を一つ出します。 (例えば「あ」がないのなら-20点とか、「う」が抜けているのなら-10点とか) 実際は多分100〜200字同士のマッチングと等価で、完全一致は期待できないため、 Dotに分枝の作成まで含めてlife_exeさせます。 結果、LifeGameからは「やっとけ。」だけで済み、詳細な実行ルーチンはDot側に集約されます。 といってもこれは分離されるだけで、どちらに書くかの違いだけなのですが、 それでも後々効いてきますので、Dot側に集約できる部分は集約しておきたいのです。 Dotは分枝の作成時に自分自身からforkする感じで、たぶんかなり増えます。 ただし親は一つなので、ここの部分は勿体ないかな、という感じでした。 (問題になるほど増えないとは思います) life_exe内には親のmapへのアクセスは大量に存在しますが、 life_exeはDot内で自走するので、引数として親ポインタを渡すことは出来ません。 従って、親ポインタはコンストラクタでメンバ変数として確保することになります。 コンストラクタで親ポインタを渡すのは、記述的には全く問題ないです。 (最初にもらった親ポインタを大事に抱えて再帰しまくることも出来ますが、、、)
|
- C++相談室 part124 [無断転載禁止]©2ch.net
993 :デフォルトの名無しさん (ワッチョイ 7b5b-xKv1)[sage]:2016/05/20(金) 23:52:28.35 ID:gU7EupTq0 - >>989
> 最近追加されたラムダですら 見てみましたが、確かにこのラムダはちょっと見にくいですし、使いにくいですね。 元はといえばC++には関数内関数が無い為、レキシカルスコープ(※)を導入できず、 ラムダのうまみも少し欠けている気がします。 (※一つずつ上の階層を探して名前が一致したらそれと見なす) g++では既に拡張が行われていると聞きましたが、先に関数内関数が欲しかったですね。 とはいえ、回答して頂いた皆様、ありがとうございました。
|