トップページ⇒tech
100コメント33KB

C++で入れ子のクラスの使いどころ

■ このスレッドは過去ログ倉庫に格納されています
0001名無しさん@お腹いっぱい。 NGNG
C++でクラスの入れ子って使ってますか?
オレ的にはソースが見にくくなってしまうので敬遠しがちだけど、
どういう状況のときに入れ子にしてます?
0002名無しさん@お腹いっぱい。 NGNG
クラスの中のクラスは構造体代わりに使ってることがおおいな‥
0003名無しさん@お腹いっぱい。 NGNG
>>1-2
has_aのことを言ってるんだよね。。。
0004名無しさん@お腹いっぱい。 NGNG
> 3
入れ子のクラスでis_aの関係ってあるの?
0005名無しさん@お腹いっぱい。 NGNG
>>4
っていうか、確認してるだけだろ?
0006み NGNG
例外で良く使う
0007名無しさん@お腹いっぱい。 NGNG
例外と、コレクション関係のプライベートなクラス。
あと、More Effective C++で紹介されているような Proxyを作るときかな。
入れ子クラスはフレンドクラスになってることが多い。
0008名無しさん@お腹いっぱい。 NGNG
>>3

class A{
public:
class B{
....
};
};

のclass Bみたいなクラスの話題でしょ?
0009名無しさん@お腹いっぱい。 NGNG
>8 それは3もわかってるようだ。
0010名無しさん@お腹いっぱい。 NGNG
STLのコンテナを独自に作るとき、
ポインタじゃまずいときは入れ子で反復子を作る。
0011名無しさん@お腹いっぱい。 NGNG
>>8
インデントできないやつは逝ってしまえ。
0012名無しさん@お腹いっぱい。 NGNG
class A{
public:
 class B{
 ....
 };
};

このBクラスって定義だけで、Aクラス内にまだ作っていませんよね?
これも入れ子?
0013名無しさん@お月いっぱい。 NGNG
class A の定義の中で class B が定義されてるんだから、入れ子でしょう。
0014名無しさん@お腹いっぱい。 NGNG
>>7
>>10
まったくそのとおり。

入れ子クラスの使いどころが判らないということは、
何にもわかっちゃいないということだ。
デザインパターンの本くらい読め。基礎だぞ。
もっと勉強しろよ、1とか2とか。
00151 NGNG
お答えしていただいた皆様、数多くのご意見ありがとうございました。
ヒジョーに勉強になりました。

> 14
まったくその通り。自分の勉強不足を改めて実感しました。
例外ですとかSTLですとか、言われてみれば確かにそのあたりが使いドコロ
だろうなあとは思うのですが、ゲーム系のプログラマをしていると、
そういう機能を使う機会がナカナカないもので。日々鍛錬せねば。

ゲーム系の方々で例外とか使ってる人がいるのかどうか、
ちょっと気になってみたり。
0016名無しさん@お腹いっぱい。 NGNG
ゲーム系プログラマです。
例外は、実機上のコードでは使っていません。理由は以下のふたつです。
・例外をとらえたとしても、リカバリのしようがない場合が多い
・開発当初はコンパイラのサポートが不安だった

とはいえ、データコンバータなどでは積極的に使用しています。

入れ子クラスについて。
いま使っているコンパイラでは、入れ子クラスをクラス宣言だけで使う
(ヘッダインクルードせずclass Foo; のみで使う)ことができないので、
外部にも見せないといけないクラスには、なるべく使わないように
しています。
0017名無しさん@お腹いっぱい。 NGNG
ゲーム系ですが、例外はそれなりに使います。
特にメモリ不足系の例外はリカバリできるケースがあるもんで‥
finalyがあればすんでしまうような事が多いですけどね。
001816 NGNG
>17
実機上でも使われているんですか! 後学のために質問させてください。

メモリ不足時の処理としては、global operator newのオーバーロード
という方法もあるかとおもいますが、例外を使ったほうが望ましい
場合がありましたら、教えていただけないでしょうか。

また、どんなリカバリを実装されているんでしょうか?
「画面上にあると良いけど なくても可」みたいな表示インスタンス
周りを削除したりするのは思いつくのですが、他にはどんな
対策があるんでしょうか?

よろしくお願いします。

#finalyはJAVAの用語でしょうか?(恥)
0019名無しさん@LV2 NGNG
ってゆーか入れ子はCOMプログラミングのためにある。

以上
0020名無しさん@LV43 NGNG
>19
なんで?
理由、説明できる?
0021名無しさん@LV2 NGNG
>20
だってオブジェクト指向最大の欠点が多重継承じゃん(ってゆーか
そう思ってます)

それを回避するのはやっぱクラスの入れ子でしょ?
そーしたプログラムを書こうとすると世間一般にCOMプログラミング
と呼ばれてるものにならない?

入れ子することで、多重継承の弊害を回避できるところから
説明しないといけないのでしょうか?^^;
0022>21 NGNG
>世間一般にCOMプログラミングと呼ばれてるものにならない?
ならならないと思うが。ネタ?
COMってマイクロソフトの提唱するComponent Object Modelのことでしょ?
いや、俺のしらないCOMもあるかもしれないので、是非ご教授を。
0023>21 NGNG
思いっきり勘違いしてる
0024名無しさん@お腹いっぱい。 NGNG
>22
はい。マイ糞ソフトのこんぽーねんとなんとかのそれです。

新たなインターフェイスを追加したいとき、
既存の2つ以上のカスタマイズ・インターフェイスのメソッド
から何個か欲しいなぁ〜とか思ったら、インターフェイスを入れ子にしません?(もしかして俺だけか?^^;)
僕の意見としては、仮想関数のアクセスに多重継承は怖くて使えません。
・・・「入れ子はCOMのためにある」はちょっと言い過ぎたかな?
「入れ子はCOMで有効」に直しちゃだめですか?(笑

このプログラムの組み方が僕の考える、COMプログラミングなんでが・・・。
全然違ってたら、みなさんどんどん指摘してくださいです・・・。
0025名無しさん@お腹いっぱい。 NGNG
>23
全部ですか?^^;
002614 NGNG
俺もゲーム系のプログラマだぞ。コンシューマーのな。
ゲームだからって例外を使わない理由は無いよ。
むしろ積極的に使うべき。
だけどメモリは operator new はオーバーロードするだけで、
例外は投げないようにしている。
ゲーム機でそんな例外が発生しても、対処のしようが無いからね。

>>21
>だってオブジェクト指向最大の欠点が多重継承じゃん

それは完全に勘違い。
多重継承こそオブジェクト指向の本質なんだよ。
Java に interface がなかったらどうなるか、想像してみなよ。
ただ単に今メジャーな言語はどれもこれをうまい形でサポートしきれていないというだけ。
002714 NGNG
>>21
>それを回避するのはやっぱクラスの入れ子でしょ?
>そーしたプログラムを書こうとすると世間一般にCOMプログラミング
>と呼ばれてるものにならない?
まさか参照カウンタつきのREPのことを言っている……?
0028名無しさん@お腹いっぱい。 NGNG
>26
>だけどメモリは operator new はオーバーロードするだけで、

「オーバーライド」ね。
0029>26 NGNG
>それは完全に勘違い。
>多重継承こそオブジェクト指向の本質なんだよ。

最大の欠点でもあり最大の利点でもあると思ってます。
0030>26 NGNG
>Java に interface がなかったらどうなるか、想像してみなよ。
なんでその話になるかよーわからんが・・・。

結局、多重継承(C++みたいな)は大規模プログラムの場合
もう消えてもいいのでは?
その解決策を考えると、JavaやCOMのようなインターフェイス
になると思うのですが?どうでしょう?


0031どうでもいいけど NGNG
COMって原理であって、継承うんぬんは
実装する言語の問題じゃないの?
0032がびょーん NGNG
ここも主旨とずれてる・・・、これにて終了ッ!

----------->8-------- キリトリ ------->8------------
0033名無しさん@お腹いっぱい。 NGNG
>18
finalyはObjectPascalの例外関連では?
0034名無しさん@お腹いっぱい。 NGNG
入れ子ってなんですか?
ForとNextの間にFor〜Nextを入れることですか?
0035名無しさん@お腹いっぱい。 NGNG
>>34 C++語でしゃべれ。
0036名無しさん@お腹いっぱい。 NGNG
>14
レスありがとうございます。こちらもコンシューマーのゲームプログラマです。

>ゲームだからって例外を使わない理由は無いよ。
>むしろ積極的に使うべき。
社内の諸先輩の意見の大勢は「アセンブラレベルでどういう仕組みで動いているか
ワカランし、メモリも実行速度もくいそうだからイヤ。使わなくても書けるジャン」
だったので、押し切ってまで使わなくても良いかと思っていました。

次のプロジェクトではもう少し使ってみようと思います。

「使うとベンリじゃないの?」とは思うのですが、「積極的に使うべき」とまでは
いまは思っていません。
よろしければ、使ってみたメリットや積極的に使うべき根拠などを教えていただけ
ないでしょうか?

# 話題がずれて申し訳ない。
003716 NGNG
名乗るの忘れてました。36=16です。
0038名無しさん@お腹いっぱい。 NGNG
> アセンブラレベルでどういう仕組みで動いているかワカラン
そんくらいしらべろや
0039名無しさん@お腹いっぱい。 NGNG
>社内の諸先輩の意見の大勢は「アセンブラレベルでどういう仕組みで動いているか
>ワカランし、メモリも実行速度もくいそうだからイヤ。使わなくても書けるジャン」

最近のゲームプログラマはそこまで技術力落ちてますか……。
そんな先輩に付き合ってたら置いてかれますよ。
0040名無… NGNG
技術が落ちてるというか…
0041名無しさん@お腹いっぱい。 NGNG
おーい、ゲームで例外を使ってるといってたやつら。
何に使ってるか、俺も聞きたいぞ。適当なこといっただけか?
まさかユーザの入力ミスの処理に使ってる、なんてこといわねーよなー
0042名無しさん@お腹いっぱい。 NGNG
俺も聞きたい<例外inゲーム
早くcoolな例外の使い方見せてよ(わくわく
0043名無しさん@お腹いっぱい。 NGNG
ウチなんてC++どころかmalloc/freeすら禁止
0044名無しさん@お腹いっぱい。 NGNG
ゲームで例外? バリバリ使ってますよ。DirectXの初期化失敗時に。
0045名無しさん@お腹いっぱい。 NGNG

実行中に動的にメモリ確保しなくちゃいけないゲームって
限られてるような気がするんですが・・・・・。
0046名無しさん@お腹いっぱい。 NGNG
まぁ、コンシューマゲームプログラミングでは、今後100年不必要なものだな。>例外機構

あ、でもデバッグのときはコンシューマでも便利か。
0047名無しさん@お腹いっぱい。 NGNG
Unrealではフェータルエラーやアサーションに例外処理を使用しています。
このとき,例外がスタックをさかのぼるのを逆手に取って,デバッグ用の
バックトレース情報を生成するようになっています。

具体的には,主要な関数は全てGUARDとUNGUARDというマクロで括られており,
このマクロでは,例外が来たら自分の関数名を所定のバッファにプッシュし
例外を投げ直すようにしてあります。こうすると,例外発生地点までのトレース
情報が生成されるわけです。

個人的にはこういう技は好きでは無いのですが,ちょっと面白いと思ったので
紹介してみました。
0048名称未設定 NGNG
面接に持ってきたシューティング、敵キャラ1個出すたびにメモリ確保してたぞ。
マシンパワーに頼りすぎというか何というか、もうちょっと考えろよって感じ。
0049>48 NGNG
ちょっと違うかもしれないけど、シューティングで敵とか弾をクラスで
処理するの流行なの?
ちょっと前にも敵の生成とか破棄をクラスで実装とかいってるHP見たんだけど。
0050名称未設定 NGNG
48っす。
うちの会社はリアルタイムゲーム関係は事実上全部Cなんでよくわかりません。
まともにC++使える人いないし。
0051名無しさん@お腹いっぱい。 NGNG
>49
やねさんとこだね
いーんじゃないの読みやすくなるし
俺は好きなやり方だよ
0052>48 NGNG
いまどきそんなこといってんなよ。古すぎ。
バランス感覚足りないよ。例えば、そうだね……
VC++6.0のヒープルーチンのスピード計ってごらん。チョー速いから。
火花のパーティクル全部クラスにしてもへーき。
読みやすさとか考えたら、むしろその面接の人の方が正しいよ。

メモリ管理ルーチンが遅かったら遅かったで、
自分でラッパー作ればいいしな。
配列で管理するにしたって結局それと同じような事するんだし。
0053>52 NGNG
PCならそれでエエかもしれんが、
コンシューマで弾一つ出すたびにメモリを確保するヤツは死刑。
速いとか遅いとかじゃなくて、メモリがたりンのよ! メモリが!
数十単位でまとめてゴソッと確保してドサッと解放するのが吉ですわよ。
0054名無しさん@お腹いっぱい。 NGNG
malloc/freeの弊害ってスピードやメモリ不足よりも
ヒープの断片化のほうが大きいと思うんだけど
そこらへんどーなの?
10時間ぶっ続けでやるとmallocできなくなって止まっちゃうとか
005553 NGNG
> 54
オレが言ったメモリが足りんっつーのは、そういうことです
断片化で困っちまいますよな。
メモリが山ほどあれば、多少断片化するくらい問題ないんですけどね。
0056名無しさん@お腹いっぱい。 NGNG
まあ、環境に合ったプログラムを書くのが当然であって
PCで組む場合気にすることはないのでは?

コンシューマーだとそうもいかないみたいだね
0057> 47 NGNG
それ、なかなか面白い使い方ですね。今度試してみるか。
005848 NGNG
>52
いや、俺が古い人間だからってのもあるんだけど、
速い環境を前提しちゃだめだと思うわけですよ。
ばらまき系のシューティングだと、54の言うように断片化しゃれにならんし。
DirectXは他のアプリに切り替える事を許してるんだし、
ユーザーの事を考えて開発するならダメじゃなかろうかと。
0059名無しさん@お腹いっぱい。 NGNG
>>53
断片化は凄く問題だけど、
STL のアロケータみたいなことをすればいいんですよ。
内部的にはブロックで確保していても、表面上は
普通に new で書けてしまいますからきれいなコードになります。
メモリ管理ルーチンを自前で起こすのはあたりまえ。
断片化には悩まされるけど、そもそも大きなブロックを
確保しないという方法が一番いけます。
ムービーですらも分割して確保。
まとめてごっそり確保するのは、始めはいいけど、最後に泣きます。
PSのゲームでもバリバリ確保しまくってるけど、
他のCで作られたゲームより劣るって事はないなぁ。

あと例外を使うのは普通。
なんでクールな使い方じゃなきゃいかんの?
弾を撃つ→管理ブロック不足→例外出力とかやらない?
0060名無しさん@お腹いっぱい。 NGNG
つーか、48はCで開発してるって言っているじゃん。>>59
参照>>50
Cで例外が使えないとは言わないけど環境次第だしな。
0061名無しさん@お腹いっぱい。 NGNG
例外、ソフトウェアリセットでタイトルに戻るときに使ってました。
邪道?
0062名無しさん@お腹いっぱい。 NGNG
>59
例外出力とは?throwするってこと、それとも文字通り画面に
エラーメッセージを出すということ?で、不足したらどう後処理するの?
006348=58 NGNG
>59

>弾を撃つ→管理ブロック不足→例外出力とかやらない?

これってデバッグ中の話だよね?
まさか製品版もそうだとは言わないよね???
0064名無しさん@お腹いっぱい。 NGNG
なんかデバッグ用ばかりだな…
これじゃassert+スタックダンプで何が悪いという気がするが。
0065名無しさん@お腹いっぱい。 NGNG
う〜ん。コンシューマでは特に不確定要素を仮定する必要ないからな〜。
まあ蓋開けとネットワーク切断くらいかな。
0066名無しさん@お腹いっぱい。 NGNG
>59
operator new@` delete をオーバーロードするってことだよね?
もしそうなら new はともかく delete は仮想関数に出来ないので非常に
困ったことになるけど、どうやって解決しているの?
0067名無しさん@お腹いっぱい。 NGNG
>65
おぉ、蓋開け&回線断のときに例外が出てくれると確かに嬉しいかもしれない。
あとメモリカード抜きの時とか。

0068名無しさん@お腹いっぱい。 NGNG
たとえば、イベント発生のとき例外で処理して悪いか? とかいってみる。
0069名無しさん@お腹いっぱい。 NGNG
「delete演算子」はまずデストラクタを呼び、次にoperator deleteを呼ぶ
0070名無しさん@お腹いっぱい。 NGNG
>68
正常系には例外を使わないのがセオリーだと思うが、あえてそのセオリーを
崩すだけの理由があるなら聞きたいな
0071名無しさん@お腹いっぱい。 NGNG
正常系に例外を使わない理由
例外はいわばlongjmpなのでgoto文と同様コードの流れが見にくくなる。
C++の場合パフォーマンスが落ちる。
catchで細かな処理(スタックの巻き戻し以上の処理)をやりにくい。
やってできないことはないが、コードが煩雑になりがち。
0072松屋のセット440円は無敵 NGNG
>>48
ま、PS以降なら速度的にはそんなに気にすることなかったりしますけどね。
68000クラスでも、自前mallocとfreeでばらまきシュー十分にイケますよ。
空き固定領域スタックに積み方式と比べてもほんの少し遅くなるだけです。
(mallocの実装がタコなら別ですが)
むしろ問題は負荷が不安定になることかな。普段は違いが分かりませんが、
処理落ちしたときにガクガク動くようになります。

んでも、WindowsとかGUI系OSの場合は、元々システムの負荷が不安定だし
「ガクガク」も誤差範囲内に収まりそうだから、どうでもいいかも(笑)。
0073名無しさん@お腹いっぱい。 NGNG
あれ、コンシューマ機はメモリが少ないから
空きメモリが断片化すると結構面倒、
って言う話だと思ってたんだけど
例外処理の実装コストの話だったのか?

0074名無しさん@お腹いっぱい。 NGNG
正常系に例外を使う理由
例外はいわばreturnなので多段ループの中からreturnで抜けるのと同
様コードの流れが見易くなる。
C++の場合、実行時のパフォーマンス低下はそれほどでもない。
catchで細かな処理(何の事か良く分からないが)をやりやすい。
例外なしでも、やってできないことはないがコードが煩雑になりがち
0075KISS NGNG
一番の弊害は「例外処理」を正常処理として行っていること。
コード見た人が混乱するよ。
0076名無しさん@お腹いっぱい。 NGNG
68>70
>正常系には例外を使わないのがセオリーだと思うが
私は、そうは思わないです。

おおむね>>74に賛成。
0077名無しさん@お腹いっぱい。 NGNG
68>75
ふむふむ、その混乱を避けるために、便利なものを捨てろ、とでも?
0078名無しさん@お腹いっぱい。 NGNG
68>71
>例外はいわばlongjmpなのでgoto文と同様コードの流れが見にくくなる。
「breakやcontinueはgotoと同じ」論争って、しってる?
0079名無しさん@お腹いっぱい。 NGNG
>>74
Object Pascalのfinallyブロックがあれば、
例外使わなくてすむのかな?

例えばこんなの
p = malloc(1)
try{
 return; // でもpはfreeされる
}finally{
 free(p);
}
0080名無しさん@お腹いっぱい。 NGNG
つーか、「例外」っていうからいかんのだ。
exceptionには例外の他の意味があるし、もともとはcatch and throw とか
呼んでたものだし。
008136 NGNG
正常系では例外を使わないのがセオリー、という立場に賛成です。
正常系でも積極的に使うべき、という意見を持った方のお話を聞いたことはなかったので、
少し詳しく教えていただけませんか? > 68@`74

PS以降のコンシューマーゲーム機上のコーディングのつもりで書いています。

68の「イベント発生」は何を指しているんでしょうか?
「蓋開け、ネットワーク切断」のようなものでしょうか?
それとも「キー入力、シューティングで弾が当たった処理」などでしょうか?
前者は正常系とみなして良いと思うので、例外による実装も妥当だと思います。
後者であれば、例外以外でも見通しの良いコーディングは可能ではないかと思います。

「breakやcontinueはgotoと同じ」論争については初めて聞きました。
ただ、longjump と break@`continue@`goto とのあいだには、複数の関数をまたいで処理の流れが
変わりうる/関数内部でしか処理流れは変わらない という性質の違いがあると思うので、
同列に論じるべきではないと思います。
関数内部での処理の流れを規制する必要はないと思いますが、複数の関数をまたいで処理の
流れが変わるのは、やはりコードが読みにくくなるのではないでしょうか。

ご意見お聞かせください。
0082名無しさん@お腹いっぱい。 NGNG
>>80
"catch and throw"は例外処理をC++で
実装したときに付けた名前なので、
最初に例外処理ありきでしょ

>exceptionには例外の他の意味があるし
ってなに?大域脱出やらそれに類する訳語はなかったけど
実際exceptionが例外以外の意味で使われてるの見たことないよ
0083名無しさん@お腹いっぱい。 NGNG
>>79
???意味不明
008480>82 NGNG
catch and throw はC++以前にLISPとかにあったんだよ。
それからexceptionを辞書でひくくらいしてごらんよ。
008574 NGNG
>>81
すまん。積極的に使うべきという意味ではない。
gotoによる実装が妥当なところはgoto使えと同じ意味で
throwによる実装が妥当なところはthrow使えと言う意味だ。

妥当かどうかの判断は「正常系」かどうかではなく、深い関数ネ
ストから戻るか、とか予期できないタイミングで戻るかなどで
するべきだ。
0086名無しさん@お腹いっぱい。 NGNG
ちゅうか、何が正常系なのかは設計次第だろ‥
008759 NGNG
デストラクタが呼ばれないかもしれないのに goto を使うの?
2重 while に気づかないかもしれないのに break を使うの?
どこで変更されたかわからないのに flag で抜けるの?
「管理番号を返す」仕様だったはずなのに、エラー時には仕様が異なるの?
成功かどうかを bool で返しているから、得たい値は引数にポインタを渡すの?

throw は高機能な goto。
前方にジャンプできないように制限されて、
複数スコープや関数を超えて戻ることができて、
デストラクタがきちんと呼ばれて、
メッセージを投げられて、
そのメッセージでポリモーフィズムできる。

あたり判定に throw を使うというのは苦しいね。
もっとイリーガルな処理に限定すべきでしょうけど、
デバッグにしか使わないというのは極論すぎ。
要は正常な処理があって、それが中断されるときに使えばいいんだよ。
0088531 NGNG
ウーン。
0089名無しさん@お腹いっぱい。 NGNG
どんどん話がズレていく。
0090名無しさん@お腹いっぱい。 NGNG
なんか、きもちわるい文章だなって思うのは、ワシだけ?
0091名無しさん@お腹いっぱい。 NGNG
>> 78
聞いたことねぇ.どっかでみれる?
0092名無しさん@お腹いっぱい。 NGNG
だれかSchemeの継続 C++で実装して
0093名無しさん@お腹いっぱい。 NGNG
例外どうこう言ってる人は、Schemeの継続とか勉強すると良いかも
0094>59 NGNG
catchが抜けててばぐったことってない?
throwする時これってみんながちゃんとcatchしてくれるか不安になったことない?
だれがthrowしてだれがcatchするか、把握するのに困難を感じたことは?
0095名無しさん@お腹いっぱい。 NGNG
Schemeの継続ってどんなことがどんな風に記述できるのでしょうか?
0096名無しさん@お腹いっぱい。 NGNG
>>87
説明に無理がないか?

>>94
例外仕様って知ってるか?
0097名無しさん@お腹いっぱい。 NGNG
>96
というとそうゆうことを知った上で「例外は正常系でもつかおう」と
いうのか?頭が腐っている
0098名無しさん@お腹いっぱい。 NGNG
>95
継続 call-with-current-continuation(c/cc)
簡単に言えばthrow-catchの逆もできる機構です。
タスクスイッチとしても利用できます。
継続はSchemeではビルトイン型の1つです。
詳しいことは'Scheme 継続'とかで検索すると色々出てくると思う
0099名無しさんi486NGNG
nige
010096(多分)NGNG
何で、こんな古いスレが上がってるんだ?

ところで、>>96は多分俺だと思うんだが、

>>97
俺は、そんなこと言ってないぞ。
>>87(=59)にも、突っ込んでるだろうが。

‥‥‥って、このスレの主役って59だったのか?
97も、もう覚えてないだろうな。
■ このスレッドは過去ログ倉庫に格納されています