1

だから私は2D空間シミュレーターに取り組んでいて、calcすべてのすべての計算を処理するリソースマネージャー''を持っています。たとえば、from calc.hpp

var calc::eccentricity (object A, object B);
var calc::distance     (object A, object B);
var calc::orbitV       (object A, object B);

など。ただし、プログラムを構造化する方法は、calcクラス内にあります。

private:
object *ship    //the currently controlled ship
object *targ    //target
object *ref     //reference (from which speeds, position, etc. are calculated)

そして、最初の例で与えられた計算をこれらで使用するために、次のように、計算関数ごとに3つの関数を記述します。

var calc::ship_ecc      (object A){
    if(!ship)    //catches null pointers
        return NAN;
    return eccentricity(*ship, A);
}

var calc::ship_ref_ecc  (){
    if(!ref)    //catches null pointers
        return NAN;
    return ship_ecc(*ref);
}

var calc::ship_targ_ecc (){
    if(!targ)   //catches null pointers
        return NAN;
    return ship_ecc(*targ);
}

の場合、およびeccentricityの場合も同じです。したがって、計算ごとに4つの関数を使用することになります。これからわか​​るように、重複したコードがたくさんあります。そして、重複したコードは悪いことです。distanceorbitVcalc.hpp

私の質問は何ですか

電話をかける方法はありますか

calc.ship.targ.eccentricity();
calc.ship.ref.eccentricity(); //or variation thereof

また

calc.ship.targ(eccentricity);
calc.ship.ref(eccentricity);  //or variation thereof

それ以外の

calc.ship_targ_ecc();
calc.ship_ref_ecc();

operator()いくつかの凝ったオーバーロードを実行したり、関数を渡したり、でfriendクラスを作成したりできるかどうか疑問に思っていますcalc31 - 53理想的には、すべての回線にしかアクセスできないようにする必要がありますpublic

ありがとう!

編集:yallの例を取得しました:https ://ideone.com/jypJQSこれは出力する必要があり、現在どのように機能しているかです

4

3 に答える 3

1

多分これはあなたの現在のコードをあまりにも変えます。しかし、calcの関数はオブジェクトのメンバーでなければならないと思います。だからあなたは次のようなことをすることができます:

ship.eccentricity(target);

私を混乱させるのは(そしておそらくここでの大きな問題は)、calcオブジェクト(プライベートメンバー)でいくつかのハードな関係を定義しているように見えることです。それらは何のためのものですか?コードから、すべての「船」にcalcオブジェクトがあると思います。はいの場合、オブジェクトと計算の間の1-1の関係を維持する代わりに、オブジェクトにコードを追加することは別の理由になります。

于 2012-12-24T22:09:23.427 に答える
1

これには少しリファクタリングが必要かもしれませんが、それだけの価値があると思います。単純なゲームの場合、OOP とポリモーフィズムを使用して問題を解決できます。

まず、objectクラスを作成します。

 class Object {

 public:
    Object();
    ~Object();
 };

このオブジェクト クラスは、ゲーム内のすべてのオブジェクト (船、キャラクターなど) の基礎となります。次に、 のサブクラスを作成しますship

 class Ship : public Object {


 };

これにより、同じ原則を必要とする将来のオブジェクトへの拡張が容易になります。

オブジェクト クラスには、いくつかの基本的なプロパティがあります。

  • 物理的 (オプション)
  • 寸法
  • 速度 (最後に計算された速度)
  • 制御 (ブール値 - 現在の制御船かどうか)

calcこれにより、 andshipクラスと難しい関係を持つ必要がなくなります。

calc次に、クラスを一般クラスに変更します。単一の船オブジェクトに依存したくありません。これは面倒です。

オプション1

calcオブジェクトごとにクラスのインスタンスを作成できます。このインスタンスは、およびクラスcalcの既に使用可能なプロパティにアクセスできます。objectship

オプション 2

calcship/object インスタンスへの参照を渡す必要がある一般的なクラスを作成します。calc->eccentricity(&ship, target);

オプション 3

可能なmanagerクラス内、または単純な「グローバル」変数内。現在制御されている船への参照を保持できます(システムがそのように機能するかどうかはわかりません)。または、船のインデックスを保存して、すべてのインスタンスを .xml 内に保持することもできますvector<&Ship>

単純なゲームでは、単純な OOP で十分ですが、さらに分離したい場合は、コンポーネント ベースのゲーム デザインの方が適しています (もちろん、OOP と組み合わせて)。

于 2012-12-24T22:28:37.390 に答える
0

そこで、これを/r/learnprogrammingに引き継いだところ、zzyzzyxx から (いつものように) 良い回答が得られました。彼の答え:

必要な 2 つまたは 3 つのパラメーターを受け取る関数を単純に持つことの何が問題なのですか? calc特別なクラスである必要はありません。calc名前空間かもしれません。あなたの設計の残りの部分でそれが理にかなっているとは確信していませんが、それをメンバー関数にして、適切なデフォルトがない場合にターゲットと潜在的に参照ポイントを指定して必要なものを計算できるようにするのはどうですか?

だから基本的に、このすべてについて心配する必要はありませんcalc.eccentricity(A, B)、ビジネス、ただ言ってくださいcalc.ship_ecc(A)calc.ship_ref_ecc()

calc.eccentricity(*calc.targ(), B)

また、calcシングルトンにするのではなく、名前空間にします。
私は今それをしに行きます。

于 2012-12-25T01:13:14.970 に答える