如何将类方法作为过剩回调传递?

shyt4zoc  于 2022-09-26  发布在  其他
关注(0)|答案(5)|浏览(109)

我知道这玩意很管用:

void myDisplay()
{
...
}
int main()
{
...
glutDisplayFunc(myDisplay)
...
}

因此,我尝试将myDisplay()函数包含到我创建的一个类中。因为我想在将来用一个不同的类来重载它。然而,编译器抱怨说

argument of type 'void (ClassBlah::)()' does not match 'void(*)()' .

以下是我想要做的:

class ClassBlah
{
   ....
   void myDisplay()
   ....
}
......
int main()
{

    ...
    ClassBlah blah
    glutDisplayFunc(blah.myDisplay)
    ...
}

有人知道如何解决这个问题吗?

nom7f22z

nom7f22z1#

首先,在非静态成员函数中有一个隐式的“this”指针,因此您需要将ClassBlah中的void myDisplay()更改为静态的。绕过这个限制很不方便,这就是为什么C++FAQ lite建议不要这么做

然后,您应该能够将函数作为ClassBlah::myDisplay传递。

这取决于您重载的动机(例如,您是要在运行时热插拔实现,还是只在编译时热切换实现?)您可以考虑一个包含指向基类的指针的实用程序“处理程序”静态类,并通过该指针委托责任。

c90pui9n

c90pui9n2#

我自己在编写C++过剩引擎时遇到了这个问题。以下是我如何解决这个问题的:

我将这些代码放在程序的顶部。cpp/main.cpp

// Function prototypes
void doRendering( void );
void processMouse( int, int ) ;
void processMouseClick(int button, int state, int x, int y);
void keyboardInput(unsigned char c, int x, int y);

在这里将这些函数分配给GLUT的回调:

glutDisplayFunc(doRendering);
glutIdleFunc(doRendering);
glutPassiveMotionFunc(processMouse);
glutMotionFunc(processMouse);
glutMouseFunc(processMouseClick);
glutKeyboardFunc(keyboardInput);

创建我自己的类,它自己处理这些,然后使我们的静态函数的内容简单地调用这个类的示例上的方法。您的Main函数应该在Main中创建一个新的类示例(在我的例子中...App*newApp)。

void doRendering( void )
{
    newApp->updateScene();
    newApp->drawScene();
}

void processMouse(int x, int y)
{
    newApp->processMouse(x, y);
}

void processMouseClick(int button, int state, int x, int y)
{
    newApp->processMouseClick(button, state, x, y);
}

void keyboardInput(unsigned char c, int x, int y)
{
    newApp->keyboardInput(c, x, y);
}

希望这能解释清楚。

lfapxunr

lfapxunr3#

我解决这个问题的方法很简单:
首先在main函数前创建一个指针。
在主函数的开头,设置指向您的类的示例的指针。
然后在新定义的渲染函数中,您可以使用全局指针访问您的对象。

/**
       Class argon is defined in external header file.

* /

Argon *argonPtr;

void renderScene();

int main()
{      
   Argon argon;
   argonPtr = &argon;

   glutDisplayFunc( render );  
}

void render()
{
   RenderStuff();
   argonPtr->Render();  
}

希望它对你有效,对我有效。

tyu7yeag

tyu7yeag4#

您可以对成员函数使用Boost绑定,例如在成员函数上创建线程:

class classA
{
public:
    void memberThreadFunc(int i);
};

void main()
{
    classA a;
    boost::thread( boost::bind(&classA::memberFunc, &a, 123) );
}
omtl5h9j

omtl5h9j5#

不能。glutDisplayFunc接受void(*)()类型的参数,而不是void (ClassBlah::)()。除非你愿意并有能力改变供过于求的根源,否则你就走运了。

许多使用回调的C API将用户指定的void*参数传递给回调,您可以使用该参数存储指向您的类的指针。然后可以传递一个自由函数,该函数将用户数据强制转换为类指针,然后调用成员函数。然而,过剩的设计方式不允许这样做。

相关问题