2012-05-12 6 views
1

Я занят созданием класса leveleditor в движке, но я застрял в передаче функции-члена в качестве параметра другой функции-члена.Передача функции-члена как параметра функции-члена

Сначала я сделал ЬурейеЕ

typedef void (LevelEditor::*CallFunctionPtr)(); 

Тогда я сделал функцию чтобы проверить, если пользователь щелкает его мышью на hitregion. Если это так, нужно вызвать другую функцию. Так что я свою первую функцию-член с 2 параметрами

LevelEditor.h

void CheckClickCollision(HitRegion* region, CallFunctionPtr callFunctionPtr); 

LevelEditor.cpp

void LevelEditor::CheckClickCollision(HitRegion* region, CallFunctionPtr callFunctionPtr) 
{ 
    if(GAME_ENGINE->GetLButtonMouseState()) 
    { 
     if(!m_bIsLeftPressed && region->HitTest(m_MousePosition)) 
      (this->*callFunction)(); 

     m_bIsLeftPressed = true; 
    } 
    else 
     m_bIsLeftPressed = false; 
} 

Тогда Я две тупые функции Пример члены:

LevelEditor .h

void LevelUp(); 
void LevelDown(); 

LevelEditor.cpp

void LevelEditor::LevelUp() 
{ 
    ++m_iCurrentLevel; 
} 

void LevelEditor::LevelDown() 
{ 
    if(m_iCurrentLevel > 0) 
     --m_iCurrentLevel; 
    else 
     return; 
} 

А теперь я хочу вызова этой функции каждый тик, чтобы проверить, есть ли удар. Так что в моей клеща функции:

CheckClickCollision(m_LeftArrowRegionPtr, LevelDown); 
CheckClickCollision(m_RightArrowRegionPtr, LevelUp); 

И здесь я получаю ошибку на LevelDown и Levelup:

Ошибка: Аргумент типа пустоте (LevelEditor :: *)() «несовместима с параметром типа» CallFunctionPtr *»

Dont знаю, как это исправить. Пробовал разные вещи, ничего не получалось

+1

Считается, что 'std :: mem_fn'? – chris

+0

Не знаю этого, но я буду его искать. Thnx;) – Thore

ответ

1

Попробуйте

CheckClickCollision(m_LeftArrowRegionPtr, &LevelEditor::LevelDown); 
CheckClickCollision(m_RightArrowRegionPtr, &LevelEditor::LevelUp); 

Для вашего удобства, здесь рабочий образец (компилятор GCC 4.7):

#include <stdio.h> 

class LevelEditor; 

typedef void (LevelEditor::*CallFunctionPtr)(); 

class LevelEditor 
{ 
public: 
    LevelEditor() {} 

    void CheckClickCollision(void* region, CallFunctionPtr callFunction) 
    { 
     (this->*callFunction)(); 
    } 

    void LevelUp() { printf("up\n"); } 
    void LevelDown() { printf("down\n"); } 

    void Test() 
    { 
     CheckClickCollision(NULL, &LevelEditor::LevelDown); 
     CheckClickCollision(NULL, &LevelEditor::LevelUp); 
    } 
}; 

int main() 
{ 
    LevelEditor e; 
    e.Test(); 

    return 0; 
} 

Другой способ назвать это:

void Test() 
    { 
     CallFunctionPtr p; 
     p = &LevelEditor::LevelDown; 
     CheckClickCollision(NULL, p); 
     p = &LevelEditor::LevelUp; 
     CheckClickCollision(NULL, p); 
    } 
+0

По-прежнему такая же ошибка, но теперь на & – Thore

+1

И без &? –

+0

Нет, просто смените ошибку на LevelEditor – Thore

0

Вы должны использовать std::function и std::bind или лямбды если таковые у вас есть вспомогательный компилятор.

void LevelEditor::CheckClickCollision(HitRegion* region, std::function<void()> callFunction) 
{ 
    if(GAME_ENGINE->GetLButtonMouseState()) 
    { 
     if(!m_bIsLeftPressed && region->HitTest(m_MousePosition)) 
      callFunction(); 

     m_bIsLeftPressed = true; 
    } 
    else 
     m_bIsLeftPressed = false; 
} 

void Test() 
{ 
    // lambda 
    CheckClickCollision(NULL, [this] { LevelDown(); }); 
    // bind 
    CheckClickCollision(NULL, std::bind(&LevelEditor::LevelDown, this)); 
} 
+0

Мы немного ближе. Функция работает, но только первая, которую я вызываю. Если я выполняю LevelUp и LevelDown, то работает LevelUp. Если я делаю LevelDown и чем LevelUp, то работает LevelDown. – Thore

+0

Это означает, что есть еще одна проблема с кодом. Например, ваш тест на столкновение (HitTest) на самом деле терпит неудачу и ничего не вызывает. Посмотрите на m_bIsLeftPressed. Он установлен в true, а затем ... Конечно, второй вызов не будет работать. –

+0

Ты меня понимаешь неправильно. Я могу нажать 100 раз на hitregion для LevelUp и LevelDown. Он будет работать 100 раз, но только в случае 1 из двух функций. Или он будет работать на LevelUp или на LevelDown. Если вызов LevelUp установлен выше LevelDown, это будет работать с LevelUp. Если LevelDown находится выше LevelUp, будет работать только LevelDown. В моих hitregions нет ничего плохого. Я использую m_bIsLeftPressed, чтобы иметь только один клик. Если кнопка мыши недоступна, GAME_ENGINE-> GetLButtonMouseState() всегда верна, поэтому для получения только одного вызова за один клик я использую m_bIsLeftPressed. Я протестировал его. – Thore

Смежные вопросы