トップページgamedev
935コメント361KB

OOとゲームプログラミング

■ このスレッドは過去ログ倉庫に格納されています
0001名無しさん@お腹いっぱい。01/11/07 23:55ID:HnYWCQK1
OOをどのように用いれば美しくゲームプログラミングを
行うことが出来るのか語り合うスレです。
0410名前は開発中のものです。02/01/06 09:03ID:???
>>409
粘着は個性だから直りません
041140902/01/06 09:22ID:???
>>410
冬休みだから暇なだけです。
0412名前は開発中のものです。02/01/06 09:29ID:???
冬眠は動物の基本。
体と心を休めなさい。
2chから24時間離れると、少しだけ休まった自分を感じる筈。
041341102/01/06 09:34ID:???
>>412
2ch を半日以上見ないと禁断症状が出ますがなにか?
0414名前は開発中のものです。02/01/06 12:26ID:???
余興も終わったみたいですし、仕事始めですし、
そろそろまじめに OO の話をしませんか?
0415  02/01/06 12:54ID:???
再発したか・・・。
治療法は上のレスで上げたゲームをOOで組んで見る事。
細部はいらない。
1)何をオブジェクトとして
2)どんな処理がどのオブジェクトに属するか
3)オブジェクト間でやり取りされるデータはなにか
を書け。
041640502/01/06 13:00ID:???
405までずっとロムってました。

冬厨の言葉を使うのは嫌だが、俺も「使い分け派」。
OOの理論だけ振りかざして「素晴らしい!みんな使えYO!」と
布教するやつは愚か。
OOを理解できなくて(というか勉強しないで)「OOは非効率的。
使えねー!」という奴もまた愚か。
ここをロムってた普通の人たちはみんなそう思っているはず。

というわけで、このスレは「ゲームプログラミングにOOは必要かどうか」
ではなくて「どのようにOOを使えば効率的なゲームプログラミングができ
るか」もしくは「OOでどのように構築するか」という風に変更したほうがよい
思うんだけど、どうでしょう?

OOが良い・悪いという議論は不毛。なぜなら良くもあり、悪くもあるから。

長文スマソ
041741502/01/06 13:14ID:???
とにかく415を実行してみなさい。
話はそれからだ。
0418 02/01/06 14:26ID:226Bizrz
どっかに OOなライブラリつくってる人いる?
いままでC++で作ると、速度度外視の厨房みたいな扱い受けたからなぁ
ベターCとしてのC++程度の物しか見たことない

まぁそもそも公開されてるものなんて初心者向けライブラリだから
簡単なものしかないかな?
0419名前は開発中のものです。02/01/06 14:50ID:???
>>418
俺作ってるよ。
I/OはTemplate Method StreamにReader/WriterをDecorate
Saver/LoaderはChain of Responsibirity
DeviceはAdapter、ResourceはSingleton
TaskはState,ControlはInterpriter
Vector/Matrix等のPrimitiveはinlineでoperator overwride
0420 02/01/06 15:04ID:???
業務連絡。
重症患者が搬入されました。
救急担当のドクターはICUへ。
0421名前は開発中のものです。02/01/06 15:51ID:???
419見て、まあそんなもんだろと思った俺は一体(;´д`)
042231502/01/06 16:07ID:???
完全に一緒に仕事をすることがない相手に対して、布教活動をお互いに(?)
行っていてもしかたないと思ったり。利用しない人はこのスレを見ないだろう
という前提で、どう利用すべきかに集中した方が意義がありそうだね。
まあ、2ちゃん的にはお祭りの方が楽しいかな?
0423名前は開発中のものです。02/01/06 16:29ID:???
人は皆罪人です。
悔い改めなさい。
0424名前は開発中のものです。02/01/07 14:21ID:???
下がり始めてるので誰かネタ振りをお願いします......って言ってもな。

というワケで私がネタ振りを
ライブラリ以外で OO をこんな風にゲームプログラミングに有効活用した!
という自慢話を聞かせてください。
0425 02/01/07 22:02ID:???
GUIは全部成功(効率↑)。
それ以外は全然駄目!OO氏ね!
0426名前は開発中のものです。02/01/08 00:12ID:???
>>425
どういう風にして、どんな失敗をしたの?
0427名前は開発中のものです。02/01/08 00:14ID:???
1000ゲッドォォォォ!!
 ̄ ̄ ̄ ̄ ̄∨ ̄ ̄ ̄       (´´
     ∧∧   )      (´⌒(´
  ⊂(゚Д゚⊂⌒`つ≡≡≡(´⌒;;;≡≡≡
        ̄ ̄  (´⌒(´⌒;;
      ズザーーーーーッ

・・・・・・・・・
 ̄ ̄ ̄ ̄ ̄∨ ̄ ̄ ̄
     ∧∧        (´;;
  ⊂(゚Д゚⊂⌒`つ (´⌒(´

ん?・・・・・・・・・
 ̄ ̄ ̄ ̄ ̄∨ ̄ ̄ ̄
     ∧∧
  ⊂(  ゚Д゚⊂⌒`つ; (´⌒(´

ドッコイショと、・・・・・・・・・
 ̄ ̄ ̄ ̄ ̄∨ ̄ ̄ ̄
     ∧∧
    (゚Д゚ ,)⌒ヽ
     U‐U^(,,⊃'〜... (´⌒;;

任務失敗と・・・・
 ̄ ̄ ̄ ̄ ̄∨ ̄ ̄ ̄
  ポ  ∧∧  ポ
  ン  (゚Д゚ ,) . ン
   (´;) U,U )〜 (;;).
(´)〜(⌒;;UU (´ )...〜⌒(`)
0428 02/01/08 00:19ID:???
↑のように映像のパーツ化は巧く行くけど、他の部分は
パーツ化できるほど仕様が固定してないってこと。
GUI以外はサブルーチン群が最強。
0429名前は開発中のものです。02/01/08 03:00ID:???
>>428
仕様っていうのは?
メソッドのシグネチャさえ固定できれば OO の方が変更は容易だと思うのですが…。
メソッドのシグネチャさえ変更しなければいけないような根本的な部分が変わってしまうのだったらグローバル関数でも全て書き直しだと思うのですが、違うのですか?
0430名前は開発中のものです。02/01/08 03:52ID:RRhnojLH
>>428
ライブラリ全般はOOの方がいいと思うけど。
I/Oとかデバイスとか抽象化しておくと便利だし。
0431名前は開発中のものです。02/01/08 06:02ID:???
結論: 慣れている方法を使え
0432 02/01/08 08:37ID:???
OOPLとOOを混同しとるらしい>>430

>>429
変更したら部品にならん。
043342902/01/08 16:39ID:???
>>432
いや、だからすげ替えるんでしょう?
「抽象的部品」を定義して、
「具体的部品 : 抽象的部品」を作る。
この「具象的部品」を「抽象的部品」として扱っていれば、
「別の具体的部品 : 抽象的部品」に置き換える事ができる。

しかも「サブルーチン群」だったら仕様が変わっても対処できる
という発言の理由は言ってないですよね?

愚推しますが、「サブルーチン群」を使っても、仕様に変更が
あった場合はコードを大量に書き直さないといけないと思いますが、
違いますか?

私が言いたいのは上記のような場合、OOPL ならば
作成するインスタンスを変更するだけで済む場合がほとんどだ。
という事です。
どうでしょうか?
0434 02/01/08 22:06ID:???
部品は小さければ小さい程、変更の可能性は小さくなります。
機械の仕様が変わってもネジを手直ししなくて良いのと同じです。
メソッドをバラしたような、部品化されたサブルーチン群は変更の可能性が
大変小さいです。
それに変更はモジュールに有るのではなく、モジュール間の関係や操作、初期値
などが多いのです。
結果として、OOPLでは再利用率が下がります。
Cだと70%−90%の再利用率を保っていましたが、OOPLに切り替えてから
20%を切っています。
0435名前は開発中のものです。02/01/08 22:18ID:???
>>434
C言語のスキルが高いが、OOPLはそれほどでもないってことだね。
Cで続けた方がいいんじゃない?
0436 02/01/08 22:20ID:???
煽ってんのか?
0437名前は開発中のものです。02/01/08 23:38ID:???
コピペ再利用なら、CもC++も関係なく高い再利用率を達成できそうだね。
043843302/01/09 05:24ID:???
>>434
> メソッドをバラしたような、部品化されたサブルーチン群は変更の可能性が
大変小さいです。
小さな部品は、対象が基本的な変数型じゃなければ(インスタンスではなく)クラスのメソッドに。
クラス名が明示される状況なら inline が有効なので呼び出しのコストもかかりません。(そのかわり多態性もない)
もっと局所的な場合には private/protected なメソッドという方法もあります。
これも呼び出しのパフォーマンスが気になる場合は inline するようにできますし、
気にならない状況であれば virtual にしておけば Template Method パターン
等を使ってトリッキーな処理ができる場合があります。

> 変更はモジュールに有るのではなく、モジュール間の関係や操作、初期値
などが多いのです。
434さんのおっしゃる「モジュール」の定義がよく理解できないので、
ちゃんとしたレスは書けないのですが、要するに根本を揺るがすような
変更がままある。という事でしょうか?
あと初期値に関しては埋め込まずに外部リースにしましょう。
これは OO かどうかとか関係なく、当たり前の事だと思うのですが…。

> Cだと70%−90%の再利用率を保っていましたが、OOPLに切り替えてから20%を切っています。

この数字はどういった計算で出されたものでしょうか?
ちゃんとした数字だとしたら、 >>435 さんの言う事も、あながちただの煽りとは
言えないかと思います。
043943502/01/09 22:55ID:???
煽ってはいないよ。オレもC言語のが得意なのでC++を使いたいやつが
チームにいるときでもCで頑張ってたよ。頑張りどころが違うのかもしれないけど。
ギリギリの納期だったりするので、C++に進むタイミングがなかなか。
次回のプロジェクトか、ターゲットハードが新しいものになったときでも挑戦しよう
かと思っているけどね。便利だろうなぁとは思うよ。
あと、OOPLとC++って一緒でいいんだよね・・・?(ぉ
044043802/01/10 03:16ID:???
>>439
> あと、OOPLとC++って一緒でいいんだよね・・・?(ぉ
ゲーム業界では一緒でいい気もしますけど...一般的には違う気がします。
私的には OOP に慣れてないうちは C++ よりも Java とか C# みたいな
単一継承で複数インターフェイス実装の OOPL をオススメしますね。
0441.02/01/10 03:30ID:???
>>434
>Cだと70%−90%の再利用率を保っていましたが、OOPLに切り替えてから20%を切っています。

熟練度90の構造化言語での開発技能の成果と
熟練度 5のオブジェクト指向開発技能の成果を比較しても
意味があるとは思えません。
まぁ、熟練度が本当に数値にできない以上は明確な事は言えませんがね。
0442名前は開発中のものです。02/01/10 03:45ID:PNlj8pol
熟練度が低い>経験が浅い>そんなにコード書いてない>再利用しようがない
て事?
0443名前は開発中のものです。02/01/10 03:49ID:FBG0h4Rw
実相継承を使ってみる。Cの遺産が使いにくくなる。
STLを覚える。Cの遺産を使わなくなる。
インタフェース継承とデザインパターンを覚える。それまでのコードを使わなくなる。
templateを使ったGenericProgramingを覚える。それまでのコードを使わなくなる。
0444名前は開発中のものです。02/01/10 04:58ID:???
燃やすまい、日本の遺産、地球の遺産。
0445名前は開発中のものです。02/01/10 05:05ID:PNlj8pol
>>443
熟練者ですか?(自分が経験激浅)
ぶっちゃけた話、どういう構造がベストなんですかね?

今のメイン組んでる人は、あるシーン用素材を元に、
必要なオブジェクトをどんどんnewしていって、
ヒープへのポインタをオブジェを管理するクラスが持つvectorに
pushしてく。
アニメーション関係はコンテナ化されています。
プリミティブ、モデル等はベースクラスから派生してて、
Render等のvirtual関数でそれぞれのCpu処理,描画処理をする。
て感じです。

難点は、殆どの処理が自動化されてて、テスト的な処理をしたくても、
シーンの素材ファイルを読まないと何も出来ない。
シーンはストリームで読み込んでて、手動で自分が作ったオブジェクトを
作る時等、初期化手続きが凄い面倒。等

STLはlist,vectorぐらいしかつかってないなあ。
0446名前は開発中のものです。02/01/10 05:08ID:???
・・・・・・・・・だから、資源は大切に。
0447名前は開発中のものです。02/01/10 05:09ID:???
PC 向けだったら資源は浪費できるでしょ
0448名前は開発中のものです。02/01/10 07:55ID:???
わかってそうでわかってない人が夢見がちな幻想として
「OOP=即座に開発効率が上がると思い込む」
というのがあるのだけど。

OOPはその前に痛みを伴う。初期の設計に欠点があれば
設計が見なおされるまでその禍根は残る。
設計が完璧になればその再利用性は飛躍的に向上するけど
問題はそのコストを支払い、堪えられるかということ。
それでもかまわないという男気あふれる者にこそOOPは
ふさわしい。
(Template Method で実装を切り離せば良いって
いう話ではなくて、より構造的な問題。)
0449名前は開発中のものです。02/01/10 08:21ID:???
GenericProgramingのいい資料ってない?
0450名前は開発中のものです。02/01/10 12:44ID:FBG0h4Rw
>>449
Modern C++ design/アンドレイ・アレキサンドレスク
今この本を注文しているんだけど、変態っぽくてなかなか良いらしいぞ。
0451名前は開発中のものです。02/01/13 22:14ID:UnhLMzSA
でも、普通にプログラミングやってれば、3割〜5割(場合によっては祖霊所)は無意識にOOしてるよね?
だから、べつにOOが良いか悪いかとか言う必要も無いと思う今日この頃。
0452名前は開発中のものです。02/01/13 23:45ID:???
認めたら最後、言語変更が行われてしまうという罠。
0453名前は開発中のものです。02/01/14 19:49ID:f6dWfBQb
>>451
単純にオブジェクトの寿命と接続の関係が整理されるだけでも、
確実にプログラムの堅牢さも作業効率も上がる。
職業プログラマは大抵経験則的にそれを分かってるし、OOP言語を用いなくとも
自前のルールでそれを実装してすらいる。
通常、OOP的アプローチが足を引っ張る状況の全ては「学習不足」に起因する。

ただ、実際の開発行為は、ほとんどの場合常に自身の学習不足と向き合わなければならないわけで…。
既に分かりきったハードで慣れ親しんだ機能を実装する「答えが見えてる」場合はともかく、
学習を伴う開発行為(出たばっかの新ハードを扱うとか)で、アプローチの仕方がわかんにゃい場合、
出だしがやたら遅くなったり、一日紙の上だけで悶々としたり、傍から見てると遊んでるようにしか
(本人苦しんでても)見えないという罠や、最初のアプローチの仕方を間違えると、その遺恨を
いつまでたっても残してしまうという罠も。

>>445
STL は俺も普段は vector と list だけだ。
ツール類なら、string iostream なんかにも出番が回ってくる。
一時期 map も使ってたが、この連想マップがベタな比較コードに勝る
速度を出したことが(経験上)ないので、最近は出番なし。
0454名前は開発中のものです。02/01/14 19:53ID:???
一度Javaで組んでみろ。
話はそれからだ。
0455名前は開発中のものです。02/01/14 20:23ID:???
>>453
罠んところ読んでると泣けてきた。
0456名前は開発中のものです。02/01/14 20:26ID:???
>>454
GCのふん詰まりを恐れて
オブジェクトがnewできない&クラス分けできない罠に陥ります。
0457名前は開発中のものです。02/01/14 23:13ID:???
>>456
インクリメンタルGCと言うものがあるのだよ
0458名前は開発中のものです。02/01/15 00:03ID:???
>>457
なんだよそれ。参照カウンタGCのこと?
0459名前は開発中のものです。02/01/15 09:02ID:???
>>458
ちょっとづつ断続的にGCしていくやつのことでは。
まとめてGCするのと違って長時間のふん詰まりがない
0460名前は開発中のものです。02/01/15 16:48ID:???
世代別GCも注目できる技術か?
046144502/01/16 01:57ID:???
タスク処理って結局、C++で再現出来るんでしょうか?
考えてみたんですが、やっぱり、関数ポインタ+(実体)ワークでないと駄目な気がする。

理由としては、
関数の切り替えがクラスのポインタだと、別途newしておく必要がある。
てことは、100個のタスクの中身が、全部A、全部Bという状況だと、
A,Bともに100個ずつクラスをnewする必要がある。
て所で詰まりました。

俺の知らない良い、解決方法があるんですかね?やっぱ。
0462名前は開発中のものです。02/01/16 02:20ID:???
>>461
デザインパターンマンセー的にはflyweightパターンが適用できると思われ
0463名前は開発中のものです。02/01/16 02:22ID:???
AB行き来するときに、delete、newすればいいんじゃないの?
046444502/01/16 03:08ID:???
>>462
デザパタはまだ調べてないです。
どういったものなんでしょうか?部分的にでも教えてくだせい。

>>463
それって、OKなんですかね?CPU負荷とか。
自分はやったことがないです。(ゲーム中にnew/delete)
0465名前は開発中のものです。02/01/16 03:12ID:???
>>461
それならメンバー関数を関数ポインタを登録しようよ・・・。
つか、Aクラス、Bクラスをメンバに持つCクラスを作って
Cクラスで切り替え管理とか。そゆいみじゃない?

 詳しくは割愛するけど、テンプレートを利用するとCに戻れな
くなるぐらい完璧なタスク処理が実現できるよー。
0466名前は開発中のものです。02/01/16 04:10ID:???
>>445
それ今うちで作っているライブラリの仕様と全く同じだよ。
その難点はそういう仕様がそのライブラリに無いのが原因だから、
つけてもらえばよいさ。
046744502/01/16 04:34ID:???
>>465
>Cクラスで切り替え管理とか。
うーん、具体的には、どうやって切り替えをするのかわからないです。

テンプレートですか、、。
あれって、大雑把に言うと、引数の型チェックしてくれるマクロ関数
ですよね?
taskクラスをテンプレートで作って、taskが使用するリソース
(GraphAPI,SoundAPI,,,等)クラスを引数で渡す。て感じですかね?
ヒント下さい。

>>466
そうすか、、。
ウチは、安くてプラグイン書きやすい3Dツールで吐き出すのを
前提にしたライブラリだと思います。多分
0468名前は開発中のものです。02/01/16 04:49ID:???
タスク処理って
A)優先順位をつけて、処理を割り振る機構

B)処理を割り振られた方が状態を遷移させながら仕事をこなす
のと二つがセットなんですね。
私は、A)だけがタスク処理だと思っていた。
0469名前は開発中のものです。02/01/16 05:00ID:???
で、B)の書き方ですが、以前のC++で書いていたプロジェクトでは
状態を整数で持っていて、switch文で切り換えていたね。
#全然、オブジェクト指向じゃないな。
0470名前は開発中のものです。02/01/16 05:01ID:???
>>467
 うんと、テンプレートの方はとりあえず忘れて。きちんと理解
できた時に必然的に解るとおもう。

 で、下のモデルみたいな感じにすればいいとおもうんだけど。

taskC
{
public:
void changeA(){ pTask = &m_TA; }
void changeB(){ pTask = &m_TB; }
private:
void Exec(){ pTask->Exec(); }

task* pTask;
taskA m_TA;
taskB m_TB;
}

まぁ、これでもいーんだけど

void Exec(){
switch(m_Mode){
case 0: m_TaskA.Exec();break;
case 1: m_TaskB.Exec();break;
}
0471名前は開発中のものです。02/01/16 05:19ID:???
恰好良く書くなら、
一つの抽象クラス(A)を継承して、関数に相当するクラスを書く。
一つの抽象クラス(B)を継承して、実体ワークに相当するクラスを書く。
Aに、Bへのポインタを引数にとるapply()関数を実装。
Bに、Aへのポインタとexecute()関数と、change_state()関数を実装。
# あっ、ややこしいね。確かに。
0472名前は開発中のものです。02/01/16 05:23ID:???
あぁ、そういえば、メンバ関数への関数ポインタを使えば
楽なのか。
#おすすめしないけど。
0473名前は開発中のものです。02/01/16 06:36ID:???
なんか話が思いっきりループしてるよーな気がする。
スレの最初のほうをご覧ありたし。
0474名前は開発中のものです。02/01/16 07:59ID:08gPS5TM
俺、仮想関数テーブルのポインタ直接書き換えてるよ。
インターフェイスクラスを多重継承して、
自前の仮想関数テーブルへのアドレスを上書きする。
C++の仮想関数と、Cの関数ポインタをオーバーヘッドなしに両立できる。
0475名前は開発中のものです。02/01/16 13:04ID:???
プロファイルしろヴォケども
0476名前は開発中のものです。02/01/16 21:30ID:???
>>474
メンバ関数ポインタを使えばいいだけ、という気がするが。
0477名前は開発中のものです。02/01/16 21:43ID:???
>>474
実装継承が絡んだ場合、this にオフセットをかまし忘れて死にそうな予感。
0478名前は開発中のものです。02/01/16 22:13ID:Hxpiv8sA
>>476
関数呼び出し方法はあくまで、C++的にしたいんですわ。
メンバ関数ポインタコールをインライン関数でラップする方法もあるけど、
仮想関数としてはつかえんでしょ。

>>477
だから多重継承を使うの。
最初の4バイトは実装継承用の仮想関数テーブルアドレス、
次の4バイトにオーバーライドするアドレスをマッピングする。
スーパークラスの仮想関数の数に影響されずに上書きできる。
0479名前は開発中のものです。02/01/16 22:28ID:???
>>478
仮想関数へのポインタを取ることは可能だけど、そういう話じゃなくて?

実装継承の話は、

class Deriv : public A, public B
{};

と定義されていた場合、Deriv 経由で B のメソッドを呼び出すときにはメソッドに渡す this ポインタは
Deriv::this では NG だって話と思われ。コンパイラの実装によるけど、たとえば Deriv に A, B のサブ
オブジェクトが順番に並んでる場合には

 reinterpret_cast<char*>(Deriv::this) + sizeof(A)

を this として渡す必要があるよね。
0480名前は開発中のものです。02/01/16 22:33ID:Hxpiv8sA
>>479
まあコンパイラの実装依存ですが、

class Deriv : public A, public B
{
int a;
};
の場合、

virtual table address A
virtual table address B
int a

とマッピングされるので、
virtual table address B
の部分を独自の関数テーブルへのアドレスに書き換えてやれば可能かと。

Bのインターフェイスを渡すときは、
this + 4とされているので、Aのサイズに依存はしないはず。
0481名前は開発中のものです。02/01/16 23:21ID:???
>>478
ハックくせー…つうか、明らかにC++の言語仕様上でやる意味ないぞ?そんなの。
単にシンボル解決の問題みたいだし、やはり>>476が順当だろう。
スレの主旨的には邪道の極みだと思うが、どーさ。
煽るつもりじゃないのでsage
0482名前は開発中のものです。02/01/16 23:24ID:???
>>481
趣味でやるなら止めないが、仕事でそんなコード出してきたら肩を叩かせていただく、ってところだな。
ま、コンパイラの吐くコードを探りつつ、いろいろやるのは面白いことは面白いよな。

参考文献
Inside the C++ Object Model
048348102/01/16 23:48ID:Hxpiv8sA
>>482
ゲームプログラムでは必須のテクだと思うぞ。
関数ポインタの使い勝手と、C++の便利さの両方を享受できる
画期的な手法。

もし移植性を高めたいなら、
仮想関数テーブルのアドレスをインスタンスメモリ内から検索してやればいい。

class B;
int adr = *((int*)&B);
int* src = ((int*)this);
for (int i=0;i<sizeof(this_class);i++){
if (adr == src[i]) src[i] = overwride_address;
}
0484名前は開発中のものです。02/01/16 23:55ID:???
んー、なんかオレ的にC++で安全面、速度面、使い易さ全てで
不満の無いタスクシステムは完成しているのだが、どーも、生成
時の記述だけ異常に複雑になるんだよなー。

 なんかよさげな方法で実装している人いる?
0485名前は開発中のものです。02/01/16 23:58ID:???
>>483
画期的っていうかswitch分で処理分岐するのじゃダメなの?
コンパイラのコード的には似たようなもんだと思うけど。
0486名前は開発中のものです。02/01/17 00:02ID:???
>>485
まぁ、人間たまに「俺は天才なんじゃないか」って思うことがあるから、落ち着くまではそのままに
しておいてあげるのが良いかと。
0487名前は開発中のものです。02/01/17 00:04ID:BamJYCnx
>>485
switch分岐はオーバーヘッドが大きいでしょ。
1、ステートのフェッチ、
2、範囲チェック×2、
3、ジャンプテーブルのフェッチ、
4、ジャンプ

仮想関数テーブルのオーバーライドなら、
コストは仮想関数を直接呼び出すのと変わらない。

コンパイラのコード的には別物です。
0488名前は開発中のものです。02/01/17 00:08ID:BamJYCnx
>>486
おいおい、折角貴重なノウハウを享受してやっているのに。
お前もちょっとは有益なことを書き込めよ。
048948502/01/17 00:21ID:???
>>487
つか、ワークシステムにおいてそのオーバヘッドがどれぐらいの
ネックになるのん?1Sync内に1000個もワークは生成しない
しょ?まぁ技術論的には面白いが。
0490名前は開発中のものです。02/01/17 00:30ID:???
>>487
default文の無いswitchは単純なJumpTableにコンパイルされるけど。
0491名前は開発中のものです。02/01/17 00:32ID:BamJYCnx
>>489
まあワークシステムのUpdate程度の用途であれば
オーバーヘッドの差は微々たる物でしょうね。
どちらかというと、new/deleteなしに、
Stateパターンを適応するのが本来の目的なのです。
0492名前は開発中のものです。02/01/17 00:35ID:???
>>491
前にも誰か書いてたが、なぜ関数ポインタを使わないんだ? C++ だと仮想関数へのポインタも取得
できるから、それで何ら問題ないと思うんだが。
0493名前は開発中のものです。02/01/17 00:38ID:BamJYCnx
>>490
それは有り得ません。
なぜなら、例えdefaultがなくとも、
変数が必ずcase内の値を取ることが保証されない限り
範囲チェックは必須だからです。
switch(a){
case 0:break;
case 1:break;
};
という構文において、aが0と1の値以外を取らないことは、
静的に保証できません。
まあ、
switch(a&1){}
とすれば最近の最適化コンパイラならdefaultを省略してくれるかもしれませんが。
0494名前は開発中のものです。02/01/17 00:41ID:???
>>486
ハイハイ。PS2だかPCは偉いね。
0495名前は開発中のものです。02/01/17 00:43ID:BamJYCnx
>>492
外部からクラスメンバを呼び出すとき、
unknown->Method()
としたいからです。
0496 02/01/17 01:06ID:???
switch使ったらライブラリ化できないでしょうが。
0497名前は開発中のものです。02/01/17 01:10ID:???
>>495
それは、単純な転送関数を書けば良い気がするけど。たとえば、下のようなコードと比較して得失は
何なんでしょ?

> 仮想関数としてはつかえんでしょ。
これなのかなぁ。

struct State
{
  void exec1() {}
  void exec2() {}
};

class Foo
  : private State
{
  void (Foo::*pMethod)();

public:
  Foo() : pMethod(&State::exec1) {}
  void method() { (this->*pMethod)(); }
};

int
main(void)
{
  Foo foo;
  foo.method();
  return 0;
}
0498名前は開発中のものです。02/01/17 01:20ID:iYo4faYa
>>478でも書いてるけど、ようはmethodを仮想関数にしたいわけです。
methodを仮想関数にすると、インライン展開できないので、
関数コール分のオーバーヘッドが増える。
この両者を解決するのが仮想関数テーブルアドレスの上書きであるということ。
0499名前は開発中のものです。02/01/17 01:33ID:???
もはや日本語じゃなくてC++で話した方がいいような気がしてきた。
0500名前は開発中のものです。02/01/17 02:08ID:jIMgxZOU
ジャンプテーブルの参照なんて、どう組み込んでもおんなじじゃん…
直接vtable書き換えるようなオバカな真似してどうするのさ。
それはコンパイラ提供側の仕様に依存しているという最悪の選択肢。
正直、仮想関数のオーバーヘッドが気になるレベルの性能が必要なら、
もっと別の解決法を考えた方がいい。

仮想関数の機構は、基底を同じくするクラスの多態性を実装するためのものなんだから、
状態別でアッパーキャストするならまだしも(これだってクラスの内容によっては
何が起きるか分からなくなるので、実装依存もいいとこなんだが)、正直その使い方は
およそ賛成しかねるなあ…。


あと、直接関係ないネタだけど。

>methodを仮想関数にすると、インライン展開できないので、

これは多くの人が誤解していることだけど、実際に仮想関数がvtable経由で
コールされるのは、アッパーキャストが絡むときのみ。
わざわざ vtable を辿らなくてもコール先が自明な場合、コンパイラは直接
関数を呼び出すコードを生成する。
inline virtual なんて、珍しくないよ?

煽るつもりじゃないのでsage
050150002/01/17 02:09ID:???
sage忘れた。
500ゲットに免じてご勘弁。
0502名前は開発中のものです。02/01/18 10:04ID:???
>>500

>実際に仮想関数がvtable経由でコールされるのは、アッパーキャストが絡むときのみ。

まともに OOP してるなら、ベースクラス通して使う事がほとんどだと思うのですが…。
050350202/01/18 10:10ID:???
書いた後に誤解を受ける文章だと気づいた。

私も vtable 書き換えなんて、よっぽどの事でもないかぎり反対です。
というかゲーム業界のプログラマって、過酷なターゲットいじり過ぎて
「まず速度ありき」なのはちょっとマズイ状況だと思う。

最適化は最後の作業ってのはソフトウェア業界の常識だと思いますけど、
そこらへんは皆さんどうお考えですか?
0504 02/01/18 10:45ID:9PXzALQL
まず速度ありき
速度の前にコード無く、コードの後に速度無し。
0505名前は開発中のものです。02/01/18 13:19ID:???
速度を考えるなら、まずはアルゴリズムの最適化
0506名前は開発中のものです。02/01/18 15:54ID:???
>>503
まず、モジュール化ありき。

ボトルネックになる部分はほんの一部に過ぎない。システムを詳細な、依存関係が少ない部分にばらして
おけば、ボトルネックを見つけて改良するもの楽。(後からアルゴリズム差し替えようなんて話は、それこそ
クラスをきっちり分けてモジュール化してないと、危なくて出来ない)
0507名前は開発中のものです。02/01/18 16:35ID:???
>>504
確かに、コードを一行も書かなければ最速だわな。(違う?)
0508名前は開発中のものです。02/01/18 17:28ID:???
>>503
まともなゲームプログラマは、
C++のコードみた瞬間にアセンブリコードが浮かぶので
無駄だらけに感じるのだろう。そっとしておいてやれ。
0509名前は開発中のものです。02/01/18 18:54ID:???
「最も速いプログラムは何もしないプログラム」ってやつか?
■ このスレッドは過去ログ倉庫に格納されています