Как передать метод класса в качестве аргумента для другой функции в С++ и openGL?
Я знаю, что это работает:
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)
...
}
Кто-нибудь знает, как решить эту проблему? Большое спасибо.
Ответы
Ответ 1
Во-первых, существует неявный указатель "this" в нестатических функциях-членах, поэтому вам необходимо изменить void myDisplay()
в ClassBlah
на статичность. Это неудобно работать над этим ограничением, поэтому С++ faq lite говорит не делает этого
Затем вы должны иметь возможность передавать функции как ClassBlah::myDisplay
.
В зависимости от вашей мотивации для перегрузки (т.е. вы собираетесь внедрять и отключать горячую версию во время выполнения или только во время компиляции?), вы можете рассмотреть статический класс утилиты "обработчик", содержащий указатель на ваш базовый класс, и делегирует ответственность за это.
Ответ 2
Я столкнулся с этой проблемой, написав сам движок С++ Glut. Вот как я работал над этим:
Я разместил их в верхней части моей программы program.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);
Назначьте эти функции для переназначения обратных вызовов здесь:
glutDisplayFunc(doRendering);
glutIdleFunc(doRendering);
glutPassiveMotionFunc(processMouse);
glutMotionFunc(processMouse);
glutMouseFunc(processMouseClick);
glutKeyboardFunc(keyboardInput);
Создайте свой собственный класс, который обрабатывает их самостоятельно, а затем сделайте содержимое наших статических функций просто вызовом методов в экземпляре этого класса. Ваша основная функция должна создать новый экземпляр класса в основном (в моем случае... 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);
}
Надеюсь, что это объяснит.
Ответ 3
Мой способ решить это просто:
Сначала сделайте указатель перед основной функцией.
В начале основной функции установите указатель на экземпляр вашего класса.
Затем в новой определенной функции для рендеринга вы можете получить свой объект с помощью глобального указателя.
/**
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();
}
Надеюсь, что это сработает для вас, для меня это так.
Ответ 4
Вы можете использовать привязку Boost для функций-членов, например, создание потока для функции-члена:
class classA
{
public:
void memberThreadFunc(int i);
};
void main()
{
classA a;
boost::thread( boost::bind(&classA::memberFunc, &a, 123) );
}
Ответ 5
Вы не можете. glutDisplayFunc
принимает параметр типа void(*)()
, а не void (ClassBlah::)()
. Если вы не хотите и не можете изменить источник перенасыщения, вам не повезло.
Многие API-интерфейсы C, которые используют обратные вызовы, передают заданный пользователем параметр void*
для обратного вызова, который вы можете использовать для хранения указателя на ваш класс. Затем вы можете передать свободную функцию, которая передает пользовательские данные указателю класса, а затем вызывает функцию-член. Тем не менее, способ, которым разработан глют, не позволяет этого.