Как передать метод класса в качестве аргумента для другой функции в С++ и 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* для обратного вызова, который вы можете использовать для хранения указателя на ваш класс. Затем вы можете передать свободную функцию, которая передает пользовательские данные указателю класса, а затем вызывает функцию-член. Тем не менее, способ, которым разработан глют, не позволяет этого.