C++ 如何从静态成员函数调用指向成员函数的指针?
我需要获得一个由标准函数指针调用的成员函数,因此我尝试抽象如下内容:C++ 如何从静态成员函数调用指向成员函数的指针?,c++,pointers,member-function-pointers,C++,Pointers,Member Function Pointers,我需要获得一个由标准函数指针调用的成员函数,因此我尝试抽象如下内容: class Sample { public: virtual void doSomething(void) = 0; }; class A : public Sample { void doSomething(void); // details omitted }; class B : public Sample { void doSomething(void); // detai
class Sample {
public:
virtual void doSomething(void) = 0;
};
class A : public Sample {
void doSomething(void); // details omitted
};
class B : public Sample {
void doSomething(void); // details omitted
};
class Executor {
public:
Executor(Sample *sample)
: func(&sample->doSomething)
{
}
static void *execute(void *data) {
Executor *pX = data;
(pX->*func)(); // error invalid access of func from static function
(pX->*pX->func)(); // error pointer to member type 'void (Sample::)()'
// incompatible with object type 'Executor'
}
private:
void (Sample::*func)(void);
};
int main(void) {
A myA;
B myB;
Executor x0(&myA);
Executor x1(&myB);
externallyInvoke(&Executor::execute, &x0);
externallyInvoke(&Executor::execute, &x1);
}
externallyInvoke
是一个Linux系统调用,它接受一个函数指针和一个数据指针。
我想使用一个静态成员函数和一个this指针作为数据
。。。我不希望像A
或B
这样的类有静态成员。所以我的想法是创建一个像classSample
这样的接口,它通过A
和B
进行扩展
我的问题是,我不知道如何从
Executor::execute
函数内部调用指向成员函数的指针。您还需要传递调用函数的Sample
实例(因为它是指向Sample
成员的指针)。有几种方法可以将实例带到一起。您可以使其成为Executor
的成员,将std::pair*
作为数据传递,或者将函数指针和实例组合为函子。对于后者,这里有一个基于lamda的方法。Lamda的优点是更通用。可以做的不仅仅是给一个类的一个成员打电话。另外,这种方法不会避免可见性规则,尽管这意味着doSomething
可能不是私有的(或者必须通过父指针调用)
模板
类执行器{
F;
公众:
执行人(F):F(F){}
静态void*执行(void*数据){
执行器*pX=静态_转换(数据);
pX->f();
返回此;//不太确定要返回什么,但只是为了使其成为格式良好的函数。。。
}
};
int main(){
myA;
B多年电价;
自动回拨0=[myA]{
myA.doSomething();
};
自动回拨1=[myB]{
myB.doSomething();
};
执行器x0(回调0);
执行器x1(回拨1);
外部yinvoke(&Executor::execute,&x0);
外部yinvoke(&Executor::execute,&x1);
}
问题是在execute
中需要两个对象-一个是Executor
的实例,它将提供func
,另一个是(从Sample
派生的类)的实例,将在其上调用func
。因此,您必须将对象存储在执行器中,而不是函数:
class Executor {
public:
Executor(Sample *sample)
: obj(sample)
{
}
static void *execute(void *data) {
Executor *pX = static_cast<Executor*>(data);
pX->obj->doSomething();
}
private:
Sample *obj;
};
int main() { // note that `void main()` is not legal C++
A myA;
B myB;
Executor x0(&myA);
Executor x1(&myB);
externallyInvoke(&Executor::execute, &x0);
externallyInvoke(&Executor::execute, &x1);
}
类执行器{
公众:
执行人(样本*样本)
:obj(样本)
{
}
静态void*执行(void*数据){
执行器*pX=静态_转换(数据);
pX->obj->doSomething();
}
私人:
样本*obj;
};
int(){//注意“无效主程序”)不是合法C++
myA;
B多年电价;
执行人x0和myA;
执行人x1和myB;
外部yinvoke(&Executor::execute,&x0);
外部yinvoke(&Executor::execute,&x1);
}
指向成员函数(例如原始的void(示例::*func)(
)的指针)标识类中的函数,但不存储对象。您仍然需要提供一个函数来调用该函数。如果您想与外部系统调用交互,您基本上必须自己重新创建std::function
。没问题,在Stack Overflow,我们是改造现有技术的大师。所以
首先,界面:
struct FunctionStateBase
{
virtual ~FunctionStateBase() {}
virtual void Invoke() = 0;
};
extern "C" void InvokeAndDelete(void * data)
{
auto state = static_cast<FunctionStateBase *>(data);
state->Invoke();
delete state;
}
现在我们需要实现MakeFunction
:
template <typename> struct FunctionState;
template <typename C, typename R>
struct FunctionState<R (C::*)()> : FunctionStateBase
{
R (C::ptmf_*)();
C * obj_;
FunctionState(R (C::ptmf*)(), C * obj) : obj_(obj), ptmf_(ptmf) {}
virtual void Invoke() { (C->ptmf_)(); }
};
template <typename C, typename R>
FunctionState<R (C::*)()> MakeFunction(R (C::*ptmf)(), C * obj)
{
return new FunctionState<R (C::*)()>(ptfm, obj);
}
模板结构函数状态;
模板
结构FunctionState:FunctionStateBase
{
R(C::ptmf_*)();
C*obj_;
函数状态(R(C::ptmf*)(),C*obj):obj(obj),ptmf(ptmf){}
虚拟void Invoke(){(C->ptmf)();}
};
模板
函数状态MakeFunction(R(C::*ptmf)(,C*obj)
{
返回新的功能状态(ptfm、obj);
}
此时,我们正在手动管理函数包装器的生命周期,请注意,InvokeAndDelete
实际上拥有函数状态的所有权。在适当的C++中,我们将封装整个系统调用调用,该类将封装内部的寿命管理。
您可以为接受参数的成员函数添加进一步的专门化;您只需要在状态中存储参数的副本。无法从静态函数访问成员变量-什么不清楚?func
是成员,不能在静态方法中使用。@user657267啊,明白了。修正了答案。那怎么修正答案呢?他想调用静态
方法上的成员函数指针,这根本不可能,让它公共
什么都不改变。@user657267,该死的不是我的日子。我没有注意到它不仅是一个成员,而且是指向另一个类的成员函数的指针。不应该是x0(myA)
bex0(&myA)
?@Wimmel是的,当然,在问题解决之前,我从OP复制了它。谢谢。@Angew我显然是想重新发明一个函子,但你的解决方案非常干净,因此:可爱:)THX
externallyInvoke(&InvokeAndDelete, MakeFunction(&A::doSomething, &myA));
template <typename> struct FunctionState;
template <typename C, typename R>
struct FunctionState<R (C::*)()> : FunctionStateBase
{
R (C::ptmf_*)();
C * obj_;
FunctionState(R (C::ptmf*)(), C * obj) : obj_(obj), ptmf_(ptmf) {}
virtual void Invoke() { (C->ptmf_)(); }
};
template <typename C, typename R>
FunctionState<R (C::*)()> MakeFunction(R (C::*ptmf)(), C * obj)
{
return new FunctionState<R (C::*)()>(ptfm, obj);
}