2

私はCの専門家ではありません。私はCS1と大学での2日間以来、Cを何もしていません。私はあちこちで少しC++を実行しましたが、しばらく経ちました。ですから、私が求めているのは、私が認識している問題を解決するための正しいパターンです。

私はかなり野心的な挑戦に挑戦することを決心し、Cでそれを行っています。私が(再)学習していることの1つは、Cでの抽象化手法と高級言語での抽象化手法の違いです。私が遭遇し、質問している問題は、具体的にはテストと機能に関係しています。

たとえば、2つの関数がfありg、特定の条件が真の場合fに呼び出します。g

void f(object* obj) {
  // ...
  if(obj->state)
    g(obj);
  // ...
}

それが実際に呼び出されていることを確認する必要がありgますが、他のさまざまなことを実行できるため、実際には実行したくありません。これは通常、インターフェース、抽象クラス、または継承を使用して、高級言語で解決さ​​れます。しかし、CIにはこれらのテクニックはありません。

実際、私が考えることができるこの問題の唯一の解決策は、関数ポインターを利用することです。直接呼び出すのではなく、へのポインターを持つようにgポインターを追加する必要があると思います。これは、テストで別の関数へのポインターに置き換えることができます。objectg

typedef struct object {
  int state;
  void (*g)(object* obj);
} object;

void f(object* obj) {
  // ...
  if(obj->state)
    obj->g(obj);
  // ...
}

次に、通常はgのインスタンスを割り当てるときにポイントしますgが、私のテストでは、obj-> gを別の関数にポイントします。この関数は、入力値を確認し、実際に呼び出されたことを示します。

これは私が今持っているアイデアですが、それがこの問題を解決するための非常に正しいC風の方法であるかどうかはわかりません。うまくいけば、私の説明は私が直面している問題を示していますが、私が本当に疑問に思っているのは、それをどのように処理するのが最善かということです。

Cでこの問題を解決するために推奨されるデザインパターンは何ですか?

4

2 に答える 2

1

gのさまざまな呼び出しで呼び出される関数を変更する場合は、パラメーターとして次のようにf渡す必要があります。gf

typedef void (*gFunc)(object* obj);

void f(object *obj, gFunc g) {
    ...
    if (obj->state) {
        g(obj);
    }
    ...
}

の関数シグネチャを台無しにしたくない場合は、上記の実装を呼び出すfためのバージョンを定義できます。f

void gNormal(object* obj);           //normal implementation of g
void gTest(object* obj);             //test version of g

void fGeneral(object* obj, gFunc g); //general implementation of f as above

void fNormal(object* obj)            
{
    fGeneral(obj, &gNormal);         //use the default version of g
}

このメソッドを選択するか、関数ポインターgをオブジェクトのメンバーにするかは、言語の観点からはおそらくほぼ同じです。オブジェクト構造にとって何がより理にかなっているのかを考慮する必要があります。

繰り返しになりますが、このようなことをたくさんしているのであれば、オブジェクト指向言語を使用する必要があるかもしれません。

于 2012-08-20T02:33:37.933 に答える
0

コンパイル時にテストケースに参加するかどうかがわかっている場合は、プリプロセッサマクロを介して制御されるgの2つの異なる実装を使用できます。たとえば、次のようになります。

#ifdef TESTING

    int g() { // implement test version here }

#else

    int g() { // implement real version here }

#endif

コンパイル時にしかわからない場合は、同じ方法でグローバル変数を使用できますが、両方の実装が同じ関数定義に含まれています。

 int g() {
     if (gTesting) {
         // implement test version here
     }
     else {
         // implement real version here
     }
 }
于 2012-08-19T21:59:37.493 に答える