两个类(A,B)-B具有指向类A非静态方法的指针

Two Classes (A,B) - B to have a pointer to class A non-static method

本文关键字:指针 静态方法 两个      更新时间:2023-10-16

我有两个对自己一无所知的类——A类、B类。

A类被称为发动机,类B称为GUI。

我希望GUI类有一个指向ENGINE类中函数的指针,这样当GUIControl上发生事件时,它会用两个参数(int,int)调用ENGINE成员函数。

以下是我想要的方式:

class CGUIManager
{
public:
    void SetControlCallback(void(*pFunctionPointer)(int,int) );
private:
    void (*m_pControlCallbackFunction)(int,int) ;
};
void CGUIManager::SetControlCallback(void(*pFunctionPointer)(int,int) )
{
    if(pFunctionPointer)
        m_pControlCallbackFunction = pFunctionPointer;
}
class CEngine
{
private:        
    void GUIControlsCallback(int iControlID, int iControlMessage);
    CGUIManager *pGUI;
};

现在,在初始化ENGINE时,我想调用:

//Set Controls Callback to CEngine Method 
pGUI->SetControlsCallback( GUIControlsCallback );

要在CGUIManager类中注册回调,它指向CEngine类中的一个方法。

我该怎么做?

提前谢谢。

如果您希望接口(或类似的东西)是oo,而不是函数指针(必须指向静态成员btw),我建议使用

class IGuiCallback
{
public:
    virtual void  GUIControlsCallback(int iControlID, int iControlMessage)=0;
};
class CGUIManager
{
public:
    void SetControlCallback(IGuiCallback*);
private:
    IGuiCallback* m_pCallback;
};
class CEngine:public IGuiCallback
{
public:
    void GUIControlsCallback(int iControlID, int iControlMessage);
private:
    CGUIManager *pGUI;
};

然后在引擎中:

pGUI->SetCallback(this);

我的代码中可能有一些语法错误,但你应该得到图片

指向成员函数的指针不是C++中的函数指针。

要稍后调用回调(使用提供的SetControlsCallback签名),调用者需要有一个有效的CEngine实例。您可以通过将指向CEngine的指针绑定到GUIControlsCallback:来实现这一点

CEngine* pEngine; // initialized somewhere
pGUI->SetControlsCallback(std::bind1st(pEngine, GUIControlsCallback));

如果您使用Boost或C++11,您最好使用它们的绑定版本(分别为boost::bindstd::bind)。

最简单的方法是使用std::function<void(int, int)作为注册回调的类型:这个对象可以用来调用任何可以用两个int调用的函数[object]。特别是,它可以调用成员函数CEngine::GUIControlsCallback(int, int),它实际上有三个参数:

  1. int型成员函数的两个明显参数
  2. 指向对象的隐式指针(变为this

这样做的方法是构造一个函数对象,该对象提供指向CEngine对象的指针作为第一个参数,并取两个整数:

struct CEngine_bind {
    CEngine_bind(CEngine* engine): engine_(engine) {}
    void operator()(int i0, int i1) { this->engine_->GUIControlsCallback(i0, i1); }
    CEngine* engine_;
};

或者,您可以使用std:bind(),这是一个创建适当绑定的函数:

CEngine engine; // ... wherever this object is coming from)
std::function<void(int, int)> callback(std::bind(&CEngine::GUIControlsCallback, &engine,
    std::placeholders::_1, std::placeholders::_2));

然后将CCD_ 12对象设置为回调。只需传递两个整数参数来调用此对象,这将导致调用引用对象上的成员函数:

callback(10, 20);

将调用

engine.GUIControlsCallback(10, 20);

std::function<void(int, int)>是可复制的,即您可以很容易地将其存储在CGUIManager类中。

如果您能够更改CGUIManager类的接口,我建议您将其推广为使用boost::function<void(int, int)>(如果用C++11编写,则使用std::function)而不是函数指针。

如果你做不到,不幸的是,你是糟糕设计的受害者。使用函数指针的C风格回调通常允许某种void*用户数据参数携带绑定到回调的任何附加信息——在这种情况下,可以将CEngine指针强制转换为void*,并编写一个自由函数包装器将void*强制转换回CEngine。然而,如果您能够更改回调接口,那么使用boost/STL函数是一种优越的技术。