如何在不暴露类详细信息的情况下传递Function指针

nav*_*nav 0 c++

我正在创建一个需要允许用户设置回调函数的库.该库的界面如下:

// Viewer Class Interface Exposed to user
/////////////////////////////
#include "dataType_1.h"
#include "dataType_2.h"

class Viewer
{
    void SetCallbackFuntion( dataType_1* (Func) (dataType_2* ) );
  private:
    dataType_1* (*CallbackFunction) (dataType_2* );
}
Run Code Online (Sandbox Code Playgroud)

在典型的用法中,用户需要在回调中访问dataType_3的对象.但是,这个对象只有他的程序才知道,如下所示.

// User usage
#include "Viewer.h"
#include "dataType_3.h"

// Global Declaration needed
dataType_3* objectDataType3;

dataType_1* aFunction( dataType_2* a)
{
    // An operation on object of type dataType_3
    objectDataType3->DoSomething();
}

main()
{
    Viewer* myViewer;
    myViewer->SetCallbackFunction( &aFunction ); 
}
Run Code Online (Sandbox Code Playgroud)

我的问题如下:如何避免对objectDataType3使用丑陋的全局变量?(objectDataType3是libraryFoo的一部分,所有其他对象dataType_1,dataType_2和Viewer都是libraryFooBar的一部分)因此我希望它们尽可能保持独立.

Mar*_*ork 6

不要在C++中使用C.

使用界面表示您想要通知的事实.
如果您希望将类型为dataType_3的对象通知给查看器中发生的事件,那么只需使此类型实现接口,然后您可以直接向查看器注册该对象以进行通知.

// The interface
// Very close to your function pointer definition.
class Listener
{ 
    public:  virtual dataType_1* notify(dataType_2* param) = 0;
};
// Updated viewer to use the interface defineition rather than a pointer.
// Note: In the old days of C when you registered a callback you normally
//       also registered some data that was passed to the callback 
//       (see pthread_create for example)
class Viewer
{
    // Set (or Add) a listener.
    void SetNotifier(Listener* l)       { listener = l; }
    // Now you can just inform all objects that are listening
    // directly via the interface. (remember to check for NULL listener)
    void NotifyList(dataType_2* data)   { if (listener) { listener->notify(data); }

  private:
    Listener*   listener;
};

int main()
{
    dataType_3  objectDataType3;  // must implement the Listener interface

    Viewer      viewer;
    viewer.SetNotifier(&objectDataType3);
}
Run Code Online (Sandbox Code Playgroud)


ltj*_*jax 5

使用Boost.Function:

class Viewer
{
  void SetCallbackFuntion(boost::function<datatype_1* (dataType_2*)> func);
private:
  boost::function<datatype_1* (dataType_2*)> CallbackFunction;
}
Run Code Online (Sandbox Code Playgroud)

然后使用Boost.Bind将成员函数指针与您的对象一起作为函数传递.

  • @Chris:请详细说明一下? (3认同)