假设您有两个(或更多)具有私有成员向量的类:
class A {
private:
std::vector<X> priv_vec;
public:
//more stuff
}
class B {
private:
std::vector<Y> priv_vec;
public:
//more stuff
}
你有一个functor-class,它有一个状态并且在泛型向量上工作(对元素或类似的东西进行排序或计数)。仿函数的状态由仿函数正在处理的第一个向量初始化。如果稍后将仿函数应用于另一个向量,它将根据状态改变其行为(以相同方式排序或在第一个向量之后修剪第二个向量,等等)
实现这样的仿函数(设计模式或函数接口?)的最佳方法是什么,而不将私有向量暴露给其他类或类的用户?
例如: 用户希望用类A的对象初始化这个仿函数,然后将这个初始化的仿函数用于B类的一个或多个对象。用户不能(也不应该)直接使用私有向量作为函数 - 算子的参数。
答案 0 :(得分: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
实例。如果您希望从课堂外实际访问该州,请选择,具体取决于。
答案 1 :(得分:0)
看起来像是从class A
的对象导入策略并将它们应用于class B
的对象的问题,唯一的区别是,所有这些都是在运行时完成的(与典型的策略相反)基础设计)。这引出了一个问题,这些政策是class A
专有的,还是我们可以隔离它们并根据需要传递它们?这应该简化设计。
答案 2 :(得分: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;
}