Как передать метод класса в качестве аргумента для другой функции в C ++ и openGL? - PullRequest
11 голосов
/ 23 марта 2010

Я знаю, что это работает:

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)
    ...
}

Кто-нибудь знает, как решить эту проблему? Большое спасибо.

Ответы [ 5 ]

9 голосов
/ 23 марта 2010

Во-первых, в нестатических функциях-членах есть неявный указатель "this", поэтому вам нужно изменить void myDisplay() в ClassBlah на статический.Неловко обойти это ограничение, поэтому в C ++ faq lite написано: не делайте этого

Тогда вы сможете передать функции как ClassBlah::myDisplay.

В зависимости от вашей мотивации к перегрузке (то есть собираетесь ли вы реализовывать горячую замену во время выполнения или только во время выполнения или только во время компиляции?), Вы можете рассмотреть статический класс "обработчик" утилиты, который содержит указатель на ваш базовый класс,и делегирует ответственность через это.

5 голосов
/ 23 марта 2010

Я столкнулся с этой проблемой при написании движка C ++ Glut самостоятельно.Вот как я обошел это:

Я разместил их в верхней части моей программы .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 здесь:*

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

Надеюсь, что это объясняет.

3 голосов
/ 14 ноября 2013

Мой способ решить эту проблему прост:Сначала сделайте указатель перед основной функцией.В начале функции 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();  
}

Надеюсь, это работает для Вас, для меня это делает.

1 голос
/ 23 марта 2010

Вы можете использовать Boost bind для функций-членов, например, создавая поток для функции-члена:

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

void main()
{
    classA a;
    boost::thread( boost::bind(&classA::memberFunc, &a, 123) );
}
0 голосов
/ 23 марта 2010

Вы не можете. glutDisplayFunc принимает параметр типа void(*)(), а не void (ClassBlah::)(). Если вы не хотите и не можете изменить источник перенасыщения, вам не повезло.


Многие C API, которые используют обратные вызовы, передают указанный пользователем параметр void*, который можно использовать для хранения указателя на ваш класс. Затем вы можете передать свободную функцию, которая преобразует пользовательские данные в указатель класса, а затем вызывает функцию-член. Однако то, как устроено перенасыщение, этого не позволяет.

...