Alc*_*ott 3 c++ function-object
我想将一个函数对象传递给一个类,该类将使用函数对象在类中做一些工作.
但问题是,我没有传递函数对象的内容.所以我想,void *在类中定义一个指针,这个指针将使用将被传入的函数对象进行初始化.
代码如下:
class A
{
public:
//...
void doSomeJob(int x)
{
(*functor)(x); //use the function object to process data x
}
private:
//...
void *functor; //function object's pointer will be assigned to this pointer
};
Run Code Online (Sandbox Code Playgroud)
但代码不起作用.我想,不能用void *functor那种方式.
我知道我可以template class用来完成这项工作,但我的问题是,我还能继续使用这项工作pointer to function object吗?
PS
为了使我的问题更清楚,可能有几个函数对象通过它们如何处理数据而彼此不同,我不会传递什么函数对象,但我知道它们中的每一个都将采用一个int参数.
就像一些答案所说的那样,我可以完成这项工作function pointer,但是函数对象比函数指针有更多的实用工具,比如states,这就是我要用的东西.
如果呼叫机构的类型未存储在呼叫机构可访问的某个位置,则无法在呼叫站点调用未知类型的功能对象.
有两种选择:
如果你可以使用C++ 11或boost,你可以使用std::functionresp.boost::function:
class A
{
public:
// ...
void doSomeJob(int x)
{
functor(x);
}
private:
std::function<void(int)> functor; // or boost::function when using boost
};
Run Code Online (Sandbox Code Playgroud)
这里的类型(以隐式形式)存储在function模板的机制内.
否则,如果您可以要求传递的所有函数对象都具有从特定基类派生的类类型,则可以创建抽象基类:
struct AbstractFunctor
{
virtual void operator()(int) = 0;
};
class A
{
public:
// ...
void doSomeJob(int x)
{
(*functor)(x);
}
private:
AbstractFunctor* functor; // or boost::function when using boost
};
Run Code Online (Sandbox Code Playgroud)
这里的类型存储在函数对象的虚拟表中.
如果你真的不能使用boost,你也可以自己编写类似的解决方案.关键词是"类型擦除",它基本上是通过动态生成来自已知基类的派生对象(如我的第二个解决方案),它知道对象的类型并可以调用它.它可能大致如下(未经测试的代码):
class int_function
{
private:
struct abstract_forward
{
virtual void call(int) = 0;
virtual abstract_forward clone() const = 0;
virtual ~abstract_forward() {}
};
template<typename Functor> struct forward: abstract_forward
{
forward(Functor f): func(f) {}
void call(int i) { func(i); }
abstract_forward clone() const { return new forward<Functor>(func); }
Functor func;
};
public:
template<typename Functor> int_function(Functor f)
{
forwarder = new forward<Functor>(f);
}
int_function(int_function const& other)
{
forwarder = other.forwarder->clone();
}
int_function& operator=(int_function const& other)
{
abstract_forward* newfwd = other.forwarder->clone();
delete forwarder;
forwarder = newfwd;
}
~int_function()
{
delete forwarder}
}
void operator()(int i)
{
forwarder->call(i);
}
private:
abstract_forward* forwarder;
};
class A
{
public:
void doSomeJob(int x)
{
functor(x);
}
private:
int_function functor;
};
Run Code Online (Sandbox Code Playgroud)