class Child;
class Parent
{
public:
void (*funcPointer)();
void (*funcPointer2)(Parent* _this);
void (Child::*funcPointer3)();
};
class Child: public Parent
{
public:
void TestFunc(){
}
void Do(){
Parent p;
p.funcPointer=TestFunc; // error, '=': cannot convert from 'void (__thiscall Child::* )(void)' to 'void (__cdecl *)(void)'
p.funcPointer2=TestFunc; // error too, '=': cannot convert from 'void (__thiscall Child::* )(void)' to 'void (__cdecl *)(Parent *)'
p.funcPointer3=TestFunc; //this works
p.funcPointer3=&Child::TestFunc; // this works too.
p.funcPointer3(); // error, term does not evaluate to a function taking 0 arguments
}
};
如何将成员函数传递给函数指针,然后我将如何调用该函数指针?
答案 0 :(得分:8)
你做不到。您可以将指针传递给静态方法,或者Parent也必须接受指向该对象的指针。
您可能希望查看boost::bind和boost::function:
#include <boost/bind.hpp>
#include <boost/function.hpp>
struct Y
{
void say(void) { std::cout << "hallo!";}
boost::function<void()> getFunc() { return boost::bind(&Y::say, this); }
};
struct X
{
//non-boost:
void (Y::*func)();
Y* objectY;
void callFunc() { (objectY->*func)(); }
//boost version:
boost::function<void()> f;
};
X x;
Y y;
x.f = boost::bind(&Y::say, boost::ref(y));
x.f = y.getFunc();
x.f();
x.func = &Y::say;
x.objectY = &y;
x.callFunc();
答案 1 :(得分:3)
为了响应您的上次修改,要形成指向成员的指针,您必须使用&
和classkey::
。正常函数的指针到函数隐式转换的函数名称没有等价。
// not valid:
p.funcPointer3=TestFunc;
// valid:
p.funcPointer3 = &Child::TestFunc;
要通过指向成员的指针访问成员,您必须使用.*
或->*
运算符。
E.g。
(this->*p.funcPointer3)();
答案 2 :(得分:1)
随着bind
和Lambda Functions的出现,我们实际上可以在C ++ 11中完成所有3个funcPointer*
。让我们先谈谈每一个,然后讨论他们在做什么:
funcPointer
尝试调用Child
方法而不接收Child
对象,因此必须保存Child
对象。子对象可以通过指针保存:bind(&Child::TestFunc, this)
或者在C ++ 14中可以按值保存:[arg = *this]() mutable { arg.TestFunc(); }
funcPointer2
尝试使用Child
调用Parent*
方法。我们可以这样做:[](Parent* arg){ static_cast<Child*>(arg)->TestFunc(); }
当然,这不会比(new Parent)->TestFunc()
更合法,所以我们假设Parent*
实际上是Child*
,如果你愿意在调用你的lambda之前让你Parent
Polymorphic Type进行验证:[](Parent* arg) {
assert(dynamic_cast<Child*>(arg) != nullptr);
static_cast<Child*>(arg)->TestFunc();
}
funcPointer3
试图存储指向Child
方法的指针,你已经有了这个工作。您只需使用Child
对象来调用它,例如:(this->*p.funcPointer3)()
。但是您必须像funcPointer3
这样指定funcPointer3 = &Child::TestFunc
,因为如果您尝试这样做:funcPointer3 = &TestFunc
您将收到错误消息:'&amp;':对绑定成员函数表达式的非法操作
接下来,函数指针或成员函数指针不能用于引用Closure Type,因此我们需要将函数指针转换为function
个对象。 (funcPointer3
只是一个成员函数指针,因此不需要转换,但我会将其转换为演示function
对象可以< / em>包含一个成员函数指针,它简化了对p.funcPointer(this)
)的调用:
class Parent {
public:
function<void()> funcPointer;
function<void(Parent*)> funcPointer2;
function<void(Child*)> funcPointer3;
};
现在我们已经改编Parent
,我们可以轻松分配,如 1 , 2 和 3 :< / p>
void Child::Do() {
Parent p;
p.funcPointer = bind(&Child::TestFunc, this);
p.funcPointer2 = [](Parent* arg) { static_cast<Child*>(arg)->TestFunc(); };
p.funcPointer3 = &Child::TestFunc;
p.funcPointer();
p.funcPointer2(this);
p.funcPointer3(this);
}
你可能知道这一点并且只是测试,但我们可以很容易地使用Parent
Child
的成员,因为我们可以创建一个新的Parent
对象Child::Do
。我将打开它并将代码抛出一个示例:http://ideone.com/yD7Rom