2

f(vector<int>& x, ....) and g(DBConn& x, ....) (....)パラメーターがすべて同一である2つの方法があります。

2つのメソッド内のコードは、xのタイプに基づいて異なるアクションを実行する1つのステートメントを除いて、完全に同一です。

in f(): we do x.push_back(i)
in g(): we do x.DeleteRow(i)

共通のコードを1つのメソッドに抽出し、2つの異なるステートメントを使用する最も簡単な方法は何ですか?

演算子()(int a)をオーバーロードするテンプレート化されたファンクターを作成することを考えていますが、それはやり過ぎのようです。

4

6 に答える 6

6
common_function(....)
{
}

f(vector<int>x,... )
{
    x.push_back(i);
    common_f(...);
}
g(DBConn& x, ....)
{
    x.DeleteRow(i);
    common_f(...);
}
于 2010-06-02T13:51:41.993 に答える
4

それぞれが異なるクラスの目的のメソッドを呼び出す2つの実装を持つ単純なアダプターを作成できます。

class MyInterface {
public:
  virtual doIt(int i) = 0;
}

class VectorImp : public MyInterface {
public:
  vector<int>& v;
  VectorImp(vector<int>& theVector) : v(theVector) {}
  doIt(int i) { x.push_back(i); }
}

class DbImp : public MyInterface {
public:
  DBConn& c;
  VectorImp(DBConn& conn) : c(conn) {}
  doIt(int i) { c.DeleteRow(i); }
}
于 2010-06-02T13:52:06.920 に答える
1
template<class T>
struct Adapter;

template<>
struct Adapter<vector<int> >
{
  static void execute(vector<int> &x, int i)
  {
    x.push_back(i);
  }
};

template<>
struct Adapter<DBConn>
{
  static void execute(DBConn &x, int i)
  {
    v.DeleteRow(i);
  }
};

template<class T>
void f(T &t, ...)
{
  ...
  Adapter<T>::execute(t, i);
  ...
}

また:

template<class T>
struct adapter_traits;

template<>
struct adapter_traits<vector<int> >
{
  typedef void (vector<int>::*PMF)(int);
  static const PMF pmf = &vector<int>::push_back;
}

template<>
struct adapter_traits<DBConn>
{
  typedef void (DBConn::*PMF)(int);
  static const PMF pmf = &DBConn::DeleteRow;
}

template<class T>
void f(T &t, ...)
{
  ...
  (t.*adapter_traits<T>::pmf)(i);
  ...
}

注:構文が間違っている可能性がありますが、あなたはその考えを理解しています。

于 2010-06-02T14:11:31.017 に答える
1

さらに別のアイデア:

template<class T>
void f(T &t, void (T::*p)(int), ...)
{
  ...
  (t.*p)(i);
}

void g()
{
  DBConn x;
  vector<int> y;
  f(x, &DBConn::DeleteRow, ...);
  f(y, &vector<int>::push_back, ...);
}
于 2010-06-02T14:16:10.173 に答える
1

ファンクターのクラシックケース:

#include <vector>
#include <DBConn.h>

// T:    The type of the object that is to be manipulated.
// A:    The type of the object that will do the manipulating
//       This may be a functor object or a function pointer.
//
// As this is a template function the template parameters will
// be deduced by the compiler at compile time.
template<typename T,typename A>
void action(T& obj,A const& action/*,....*/)
{
    // Do Stuff
    action(obj,5);
    // Do more Stuff
}

// Functor object
struct MyVectorAction
{
    // Just defines the operator()
    // Make sure it is a const method.
    // This does the unique bit of code. The parameters should be what you pass into action
    void operator()(std::vector<int>& data,int val) const   {data.push_back(val);}
};
void f(std::vector<int>& x)
{
    action(x,MyVectorAction()/*.... Params ....*/);
}


struct MyDBConnAction
{   void operator()(DBConn& data,int val) const   {data.DeleteRow(val);} };
void g(DBConn& x)
{
    action(x, MyDBConnAction());
}

int main()
{
    std::vector<int>    x;

    f(x);
}
于 2010-06-02T14:35:07.357 に答える
0

呼び出すもの(...)のパラメーターを持つ関数を作成できます。この関数は、f()とg()で同じロジックを実装できます。次に、f()とg()の実装を変更して、ロジックを複製する代わりに、この新しい関数を呼び出すことができます。ただし、独自の行の前後で何かを複製する場合は注意が必要です。その場合、2つの関数が必要になることがあります。いずれにせよ、これはコードのブロックを複製するよりも望ましいと思います。

于 2010-06-02T13:50:46.613 に答える