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
这样的类有静态成员。所以我的想法是创建一个像class
Sample
这样的接口,它通过
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)
be
x0(&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);
}