![](/img/trans.png)
[英]How to invoke pointer to member function when it's a class data member?
[英]How to invoke pointer to member function from static member function?
我需要获得一个由标准函数指针调用的成员函数,所以我尝试抽象这样的东西:
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-pointer作为数据。
......我不希望像A
或B
这样A
类有静态成员。 所以我的想法是创建一个类Sample
的接口,它由A
和B
扩展。
我的问题是我不知道如何从Executor::execute
函数内部调用指向成员函数的指针。
问题是,你需要两个对象里面execute
-一个实例Executor
将提供func
,另一个是(从派生的类)的实例Sample
上func
将被调用。 所以你必须将对象存储在Executor
,而不是函数:
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);
}
指向成员函数的指针(例如您的原始void (Sample::*func)()
)标识类中的函数,但不存储该对象。 您仍然需要提供一个来调用该函数。
您还需要传递一个Sample
实例来调用该函数(因为它是一个指向Sample
成员的指针)。 有几种方法可以实现实例。 您可以使它成为Executor
的成员,将std::pair*
作为data
传递,或者您可以将函数指针和实例组合为仿函数。 这是针对后者的基于lamda的方法。 Lamda具有更多功能的优点。 除了调用一个类的一个成员之外,还可以做更多的事情。 作为奖励,这种方法不会避免可见性规则,尽管这意味着doSomething
可能不是私有的(或者它必须通过父指针调用)。
template<class F>
class Executor {
F f;
public:
Executor(F f): f(f){}
static void *execute(void *data) {
Executor<F> *pX = static_cast<Executor<F>*>(data);
pX->f();
return this; // not quite sure what you intend to return, but just to make this a well formed function...
}
};
int main() {
A myA;
B myB;
auto callback0 = [myA]{
myA.doSomething();
};
auto callback1 = [myB]{
myB.doSomething();
};
Executor<decltype(callback0)> x0(callback0);
Executor<decltype(callback1)> x1(callback1);
externallyInvoke(&Executor::execute, &x0);
externallyInvoke(&Executor::execute, &x1);
}
如果你想与外部系统调用进行交互,你基本上必须自己重新发明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;
}
以下是您使用它的方式:
externallyInvoke(&InvokeAndDelete, MakeFunction(&A::doSomething, &myA));
现在我们需要实现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);
}
此时我们手动管理函数包装器的生命周期,并注意InvokeAndDelete
实际上取得了函数状态的所有权 。 在适当的C ++中,我们将整个系统调用调用包装在一个内部封装生命周期管理的类中。
您可以为带参数的成员函数添加更多特化; 你只需要在状态中存储参数的副本。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.