将类成员函数存储在模板中

Store class member function in a template

本文关键字:存储 成员 函数      更新时间:2023-10-16

我需要在某个地方存储这样的成员函数指针:

void Class1::function1(int a, int b)
{
  ...
}
struct parameters
{
   int a;
   int b;
}
myStoreClass.store(&Class1::function1, parameters);

然后可以这样称呼它:

myStoreClass.call();

以便使用适当的参数来调用该函数。

既然它是一个成员函数,我想我也应该存储一个Class1对象指针,但我如何用模板存储成员函数指针呢?

您需要参数化成员函数所在对象的类型,并将指针传递给该函数。为了调用成员函数,还需要传递一个指向对象的指针和调用的参数。这是一个示例:

class Foo 
{
public:
    void DoIt (int a, int b)
    {   
    }   
};
class Bar 
{
public:
    void DoItAgain (int x, int y)
    {   
    }   
};
template <typename Obj>
void DoSomething (Obj* that, void (Obj::*fnThat)(int,int), int i, int j)
{
    (that->*fnThat)(i, j); 
}
int main()
{
    Foo foo;
    Bar bar;
    void (Foo::*fnFoo)(int,int) = &Foo::DoIt;
    (foo.*fnFoo)(42,43);
    DoSomething (&foo, fnFoo, 99, 100);
    DoSomething (&bar, &Bar::DoItAgain, 200, 300);
}

如果您使用的是C++11编译器,那么它相当简单。给定此类:

class Class1 {
public:
    void function1(int a, int b);
};

您可以使用std::bind:准备一个调用

#include <functional>
// ...
Class1 class1Obj;
auto myStore = std::bind(&Class1::function1, &class1Obj, 10, 20);

你以后可以用来称呼它

myStore();
// The above has the same effect as:
// class1Obj.function1(10, 20);

实际上,您根本不需要StoreClass(这基本上就是std::bind所做的。)

这只是一个例子。显然,您需要确保在执行调用时,您正在调用Class1::function1()的Class1实例(上例中为class1Obj)仍然存在。

如果你没有使用C++11,那么你可以使用Boost:

#include <boost/function.hpp>
#include <boost/bind.hpp>
// ...
boost::function<void()> myStore = boost::bind(&Class1::function1,
                                              &class1Obj, 10, 20);

呼叫是相同的:

myStore();

在这两种情况下,bind返回的函数类型都是void ()。这意味着一个函数返回void,不接受任何参数(因为它们已经被绑定"吞噬"了。)因此,如果您仍然需要创建一个模板来参数化您可以存储的成员函数调用的类型,那么您只需要对成员函数的返回类型执行此操作,而不需要对其参数执行此操作。例如:

template <typename T>
// ...
std::function<T ()> storedCall;
// or with Boost:
// boost::function<T ()> storedCall;

请注意,Boost.Bind和Boost.Function是仅用于头的库。这意味着它们很容易使用,根本不需要链接到任何库。