是否可以声明一个可以指向任何类的成员函数的函数指针(非C ++ 11)(读取:不是特定的类)?
例如,如果我有A,B和C类,C中有一个声明的函数指针,我想在指向B的成员函数之一和A的成员函数之间切换指针。 C ++是否允许这样做?
答案 0 :(得分:3)
boost::function
可以与boost::bind
:
#incluce <boost/function.hpp>
#include <boost/bind.hpp>
struct A{ void f(); };
struct B{ void g(); };
struct C{
boost::function<void()> _func;
};
int main(){
A a; B b; C c;
c.func = boost::bind(&A::f, &a);
c.func();
c.func = boost::bind(&B::g, &b);
c.func();
}
答案 1 :(得分:2)
是的,你可以,但你必须删除一些类型的安全性并跟踪 this 指针以及成员函数。
您可以在http://www.codeproject.com/Articles/11015/The-Impossibly-Fast-C-Delegates中查看用例。基本思想是将对象指针存储为void指针,并通过静态方法重定向函数调用。
#include <iostream>
using namespace std;
struct A { void foo() { cout << "A::foo\n"; } };
struct B { void foo() { cout << "B::foo\n"; } };
class C
{
public:
C() : object_ptr(0), stub_ptr(0) {}
template <class T, void (T::*TMethod)()>
static C from_method(T* object_ptr)
{
C d;
d.object_ptr = object_ptr;
d.stub_ptr = &method_stub<T, TMethod>;
return d;
}
void operator()() const
{
return (*stub_ptr)(object_ptr);
}
private:
typedef void (*stub_type)(void* object_ptr);
void* object_ptr;
stub_type stub_ptr;
template <class T, void (T::*TMethod)()>
static void method_stub(void* object_ptr)
{
T* p = static_cast<T*>(object_ptr);
return (p->*TMethod)();
}
};
int main()
{
A a;
B b;
C c = C::from_method<A, &A::foo>(&a);
c();
c = C::from_method<B, &B::foo>(&b);
c();
return 0;
}
上面的代码应该打印
A::foo
B::foo
此解决方案比使用std::function
更快,因为它不需要为数据分配堆存储,但这可能仅用于引用成员函数(不同于std::function
声明所有可调用的所有权对象)。
答案 2 :(得分:1)
这是不可能的。当您声明类的成员函数时,该函数具有隐式this
参数,因此即使您编写void A::func(int i)
,该函数实际上也具有此签名:
void func(A *const this, int i)
你需要一些像Boost.Function和Boost.Bind这样的东西来共同做你想要达到的目标:
boost::function<void (int)> func;
A* a = new A;
func = boost::bind(&A::func, a, _1);
答案 3 :(得分:0)
不,但你可以让A和B有一个共同的基类X,然后你可以对A和B使用T (X::*)(U...)
(假设T和U是相同的)。
或者您只需使用boost::variant
。
答案 4 :(得分:0)
不,你不能。
如果可以,那就没有意义了。想象一下,你可以,你有一个类型A的对象,并调用一个指向类型B的成员函数的成员函数指针。突然在B的成员函数中,你将有一个this指针,指向该地址一个A对象,但类型为B*
。
这取决于你试图解决的真正问题(也许你应该问过这个问题),但是你可以尝试让所有类都有一个共同的基本功能(可能是虚拟的)并使用指向这些功能的指针,但除非你向我们提供了更多细节,我们只能猜测。
另一个更广泛的替代方案可能是使用boost::function
个对象,这些对象已经绑定到要调用成员函数的对象上。