2

プライベート メンバー ベクトルを持つ 2 つ (またはそれ以上) のクラスがあるとします。

class A {  
private:  
 std::vector<X> priv_vec;  
public:  
 //more stuff  
}  

class B {  
private:  
 std::vector<Y> priv_vec;  
public:  
 //more stuff  
}  

そして、状態を持ち、汎用ベクトルで機能するファンクタークラスがあります(要素の並べ替えやカウントなどを行います)。ファンクターの状態は、ファンクターが作業している最初のベクトルによって初期化されます。ファンクターが後で別のベクターに適用される場合、状態に応じて動作が変わります (同じ方法でソートするか、最初のベクターと同じ数の要素の後に 2 番目のベクターをトリミングするなど)。

プライベートベクターを他のクラスまたはクラスのユーザーに公開せずに、そのようなファンクター (設計パターンまたは関数インターフェイス?) を実装する最良の方法は何ですか?

例: ユーザーは、クラス A のオブジェクトでこのファンクターを初期化し、クラス B の 1 つまたは複数のオブジェクトに対してこの初期化されたファンクターを使用したいと考えています。ユーザーはプライベート ベクトルを使用できません (使用すべきではありません)。ファンクターの関数引数として直接。

4

3 に答える 3

1

まず、ファンクタの状態に注意してください。

アルゴリズムのほとんどの STL 実装は、ファンクターをコピーする可能性があるため、通常は外部構造で状態を抽出する必要があります。

さて、ファンクターの適用については、簡単です: クラスにテンプレート メンバー関数を宣言させます!

class A
{
public:
  template <class Functor>
  Functor Apply(Functor f);

private:
};

class B
{
public:
  template <class Functor>
  Functor Apply(Functor f);
};

// Usage
MyFunctor f;
A a;
B b;
b.Apply(a.Apply(f));

ファンクターに関しては、状態が必要な場合:

// Alternative 1
class FunctorState {};

class Functor
{
public:
  Functor(FunctorState& state): m_state(state) {}

  // some operator()(...)

private:
  FunctorState& m_state;
};

// Alternative 2
class Functor
{
  struct FunctorState {};
public:
  Functor(): m_state(new FunctorState) {}

  // some operator()(...)

private:
  boost::shared_ptr<FunctorState> m_state;
};

このようにして、すべてのコピーが同じインスタンスFunctorを指します。FunctorStateクラスの外部から実際に状態にアクセスするかどうかに応じて選択してください。

于 2009-10-29T08:26:47.913 に答える
0

class Aのオブジェクトからポリシーをインポートしてのオブジェクトに適用する問題のように見えますがclass B、唯一の違いは、これらすべてが実行時に実行されることです(通常のポリシーベースの設計とは対照的です)。これは疑問を投げかけます、これらのポリシーは独自のものclass Aですか、それともそれらを分離して必要に応じて渡すことができますか?それはdeisgnを単純化するはずです。

于 2009-10-29T08:46:11.820 に答える
0

テンプレートに基づくソリューション。

#include <iostream>
#include <string>
#include <vector>

// Wraps up a vector of type T and exposes a
// simple interface to access it.
template <class T>
class A
{  
public:  
  A(const std::vector<T>& v) : priv_vec(v) { }
  virtual size_t count() const { return priv_vec.size(); }
  virtual T operator[](size_t index) const { return priv_vec[index]; }
private:  
  std::vector<T> priv_vec;  
};  

// A sample functor with state.
// The state is the size and current index of the vector object.
class Functor
{
public:
  Functor() : _size(0), _index(0) { }

  // Prints the element at the current index.
  // If the index exceeds size, it is reset to 0.
  template <class T>
  void operator()(const A<T>& b)
  {
    if (_size == 0) _size = b.count();
    if (_index >= _size) _index = 0;
    std::cout << b[_index++] << '\n';
  }

private:
  size_t _size;
  size_t _index;
};

int
main()
{
  // Some tests.

  std::vector<int> int_vec;
  int_vec.push_back(1);
  int_vec.push_back(2);
  int_vec.push_back(3);
  A<int> a(int_vec);

  std::vector<std::string> str_vec;
  str_vec.push_back("aaaa");
  str_vec.push_back("bbbb");
  str_vec.push_back("cccc");
  A<std::string> b(str_vec);

  Functor f;
  f(a); // 1
  f(b); // bbbb
  f(a); // 3
  f(a); // 1
  f(a); // 2
  f(b); // cccc

  return 0;
}
于 2009-10-29T10:13:31.517 に答える