5

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

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

我怎么能绕过这个?

类似的问题是:使用 C++ 类成员函数作为 C 回调函数,他们建议将方法静态化。但是我不能这样做,或者我不知道我怎么能这样做。

代码

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。

4

4 回答 4

7

你试图做的事情是不可能的。这glut其实是自己的错。

事情是这样的:

  • glut想要调用一个函数,而不给它数据,
  • 你希望你的函数使用一些数据,

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

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

于 2012-08-03T09:14:21.057 回答
3

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

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

于 2012-08-03T09:18:40.950 回答
2

使用指向您的 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 构造函数的任何代码均不可见。

于 2012-08-03T11:03:01.617 回答
1

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

像这样的东西:

//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();
}
于 2012-08-03T09:14:39.120 回答