【问题标题】:To pass a pointer to a member function将指针传递给成员函数
【发布时间】:2012-08-01 07:43:14
【问题描述】:

我有一个带有实例函数(或方法?)的类。在一个实例中,我尝试将指向这些函数的指针传递给一个库。该库需要静态函数。

当我将指针传递给回调函数时,编译器会抱怨我的函数不是静态的。我试图将它们设为静态,但如果这样做,我将无法从函数中访问实例字段。

我该如何解决这个问题?

类似的问题是:Using a C++ class member function as a C callback function 他们建议将方法静态化。但是我不能这样做,或者我不知道我怎么能这样做。

代码

GlutController::GlutController (int argc, char **argv) {

   // stuff ..

   // Register callbacks
   glutSpecialFunc( OnSpecialKeys );  // Error, need static functions
   glutReshapeFunc( OnChangeSize );   // Error...
   glutDisplayFunc( OnRenderScene );  // Error...

   // stuff ..
}

GlutController::~GlutController() {

}

void GlutController::OnChangeSize(int aNewWidth, int aNewHeight){

   glViewport(0,0,aNewWidth, aNewHeight);
   mViewFrustrum.SetPerspective( APP_CAMERA_FOV,             // If this function is 
            float( aNewWidth ) / float( aNewHeight ),        // static, this won't 
            APP_CAMERA_NEAR,                                 // work
            APP_CAMERA_FAR );
   mProjectionMatrixStack.LoadMatrix(                        // Same here
            mViewFrustrum.GetProjectionMatrix() );
   mTransformPipeline.SetMatrixStacks(mModelViewMatrixStack, // Same here  
            mProjectionMatrixStack);

}

void GlutController::OnRenderScene(void){
   mGeometryContainer.draw();                                // Won't work if static
}

void GlutController::OnSpecialKeys(int key, int x, int y){
   mGeometryContainer.updateKeys(key);                       // Won't work if static
}

免责声明:我刚开始使用 C++。我阅读了所有 Accelerated C++,这是我第一个尝试该语言的项目。我的背景是 Java。

【问题讨论】:

标签: c++ function-pointers glut member-function-pointers freeglut


【解决方案1】:

您尝试做的事情是不可能的。这实际上是glut 的错。

事情是这样的:

  • glut 想调用一个函数,但不给它数据,
  • 您希望您的函数使用一些数据,

这是相互冲突的需求。我相信glut 决定您可以安全地使用全局变量。

因此,一种解决方案是使用静态函数,带有静态数据。或者更好的解决方案是切换到SDL

【讨论】:

  • 我对 glut 了解不多,但听起来它需要一些可调用的东西,不需要任何参数(包括隐式参数)。那么,一个适当构造的std::function 就不能解决问题吗?
  • 任何开发了不能接受用户定义参数的不透明库函数(例如用于回调)的人都应该被解雇,晋升为营销/销售人员或给予经济激励去工作为竞争对手的公司。
  • @Shahbaz 我正在尝试做一个简单的演示,我读到 glut 在样板代码方面与 SDL 相比使用起来非常简单。此外,我正在使用“OpenGL SuperBible”一书来指导我。我认为使用静态/全局将是不可避免的,或者像尼克在下面的回答中所说的那样使用单例。
  • @MartinJames,同意了。和it's not just that!。我认为在设计过剩时,人们并不擅长预见。要么,要么微软参与其中。
  • @AntoineG,您需要对 SDL 做的额外工作就是编写一个 3 行主循环并删除所有给定的回调行,以及一个 while/select,它会根据来自队列。相信我,如果你只想画几个三角形,过剩变得很难控制。顺便说一句,我也从同一本书中学习了openGL,但是用SDL替换了过剩代码,重点更多的是openGL部分,所以它不应该妨碍你。
【解决方案2】:

简而言之,你不能。 C++ 成员函数实际上“链接”到对象的实例。在较低的层次上,它们有一个额外的参数,实际上是指向该对象实例的指针。

因此,您必须使用静态函数,并且由于 glut 不允许您传递可识别当前实例的参数,因此您必须想出一些解决方法。最简单的解决方法是使用静态成员。如果你的 GlutController 是单例的(我认为是),你会没事的。

【讨论】:

    【解决方案3】:

    使用指向您的 GlutInstance 的文件范围的静态变量(静态函数 + 静态数据,如另一个答案中提到的)是可能的并且显然是安全的。

    static GlutController* s_this;
    
    static void s_OnChangeSize(int w, int h) { s_this->OnChangeSize(w, h); }
    
    GlutController::GlutController (int argc, char **argv) { 
       s_this = this;
    
       glutSpecialFunc(s_OnSpecialKeys);
    }
    
    GlutController::~GlutController() { s_this= 0; } 
    
    void GlutController::OnChangeSize(int w, int h) { /* non-static stuff */ }
    

    s_this 仅在本地文件中可见,例如对从另一个文件调用 GlutController 构造函数的任何代码均不可见。

    【讨论】:

      【解决方案4】:

      你应该有一个static method 和一个instance(可能是静态的)来从static 函数调用instance 的成员函数

      类似这样的:

      //static method
      void MyClass::myCallback()
      {
          static MyClass instance; //or you can store your in instance in some Singleton, or
          //possibly create a temporary
          instance.nonStaticMethod();
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-11-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-05-16
        相关资源
        最近更新 更多