1

ネット上で関数オブジェクト (呼び出し先) に関する例をいくつか見つけましたが、コールバック関数 (呼び出し元) の引数としてそれらを使用する方法を示していませんでした。したがって、私は自分で作成しました:

class CBase
{
public:
 virtual int operator()(int a, int b)
 {
  return 10;
 }
};

class CSmaller: public CBase
{
public:
 int operator()(int a, int b)
 {
  return a < b;
 }

 int Compute(int a, int b)
 {
  return a < b;
 }
};

class CLarger: public CBase
{
public:
 int operator()(int a, int b)
 {
  return a > b;
 }

 int Compute(int a, int b)
 {
  return a > b;
 }
};

int caller(CBase &f, int x0, int x1) 
{
 return f(x0,x1);
}

int main()
{
 CLarger callee1; /*this callee is being called by caller*/
 CSmaller callee2; /*idem*/
 int q=caller(callee1,0,1);
 int z=caller(callee2,0,1);
 printf("%d\n",q);
 printf("%d\n",z);
}

これらの STL 関数オブジェクト (より大きな Less など) は、このように実装されていますか? つまり、それら (CLarger と CSmaller) は、クラスごとに拡張された仮想関数を持つリレーション/共通アンカーを持っていますか、それともいくつかの一般的な関数オブジェクトにすることもできますか (2 つの引数を持つ () 演算子を実装する限り) ? このように(ただしテストされていません):

template<class F>
float integrate(const F &f,float x0,float x1) 
{
 ..f(x)..;
}

float derive(const F &f,float x0,float x1) 
{
 ..f(x)..;
}

class CSquare 
{
public:
 float operator()(float x)
 {
  return x*x;
 }
};

class CTwoX 
{
public:
 float operator()(float x)
 {
  return 2*x;
 }
};

これが正しい方法である場合、これらの無関係なクラスを非 STL の方法で実装するにはどうすればよいでしょうか? テンプレートを使用して基になるメカニズムを保持することは知っていますが (そのように関連している)、タイプのみが異なります。しかし、そのような関係 (つまり、同じアンカー) は必要なのでしょうか?

関数オブジェクトでオーバーロードされた () を使用しているのは、利便性のためだけですか? CLarger の Compute も使えるからです。たとえば、Larger と Smaller のメンバーを持つクラス CCompute で、これらの分離されたクラス (さまざまな機能に virtual を使用) をマージすることもできます。ところで、派生と統合をクラスに入れることもできると思います。私の質問は理にかなっていますか、それとも私の考えはSTL理論と矛盾していますか?

4

2 に答える 2

1

継承またはテンプレートのいずれかの方法を使用できます。ただし、どちらも要件ではありません。STL 関数はテンプレート化されているため、式が必要に応じて機能する限り、f(x)何でも渡すことができますf(関数ポインター、ファンクターなど、呼び出し先と呼ばれるもの)。

注:f(x)は単なる例であり、パラメーターの正確な数は、使用される特定の STL 関数によって異なります。

継承の利点は、一般的な動作を基本クラスにカプセル化し、実行時に実際の型に基づいて実行できることです。

テンプレートの利点は、(テンプレート パラメーターに基づいて) 任意の型で使用できることです。そのためoperator()、各クラスでオーバーロードできますが、各型を処理できるテンプレート クラスを作成する方が簡単な場合があります (テンプレートの特殊化を使用する場合)。種類によっては特別な取り扱いが必要です)

テンプレートを使用すると、実際のテンプレート パラメータ タイプの組み合わせごとに異なるタイプが作成されることに注意してください。

于 2012-04-15T16:03:18.523 に答える
0

関数の引数 (述語など) を受け入れる STL アルゴリズムは、通常、「関数のような」インターフェイスに一致する限り、引数の作成方法を気にしません。必要なのは、次の行に沿ってテンプレート引数推定で型を推定することだけです

template< typename FwdIter, typename Pred >
FwdIter find_if( FwdIter first, FwdIter last, Pred pred );

/* .. etc ... */

bool is_equal_to_one(int n) { return n == 1; }

int main()
{
    std::vector<int> foo;
    std::vector<int>::const_iterator iter;
    iter = std::find_if( foo.begin(), foo.end(), is_equal_to_one );
}

Pred他の方法 (関数、ファンクター、std::関数など) で実装するには、型を実装する方法が多すぎます。Predfind_if 関数は、のインターフェースに一致するものに依存しますbool (*FwdIt)

于 2012-04-15T16:07:07.730 に答える