如果函数对象的类型未存储在调用机制可访问的某个位置,则您不能在调用站点调用您不知道的类型的函数对象。
有两种选择:
如果可以使用 C++11 或 boost,则可以使用std::function
resp。boost::function
:
class A
{
public:
// ...
void doSomeJob(int x)
{
functor(x);
}
private:
std::function<void(int)> functor; // or boost::function when using boost
};
这里类型存储(以隐式形式)在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
};
这里类型存储在函数对象的虚拟表中。
如果你真的不能使用 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;
};