I've been trying to assign a function pointer (of a class) to a member function (of another class) like this:
--- Game.h ---
#ifndef GAME_H
#define GAME_H
#include "Screen.h"
class Game
{
private:
void (*HandleCurrentScreen)();
public:
void SetScreen(const Screen& newScreen);
};
#endif
--- Game.cpp ---
#include "Game.h"
#include "Screen.h"
void Game::SetScreen(const Screen& newScreen)
{
HandleCurrentScreen = newScreen.Handle; //Produces the error
}
--- Screen.h ---
#ifndef SCREEN_H
#define SCREEN_H
class Screen
{
public:
void Handle();
};
#endif
--- Screen.cpp ---
#include "Screen.h"
void Screen::Handle()
{
...
}
I get this error:
error C3867: 'Screen::Handle': function call missing argument list; use '&Screen::Handle' to create a pointer to member
It seems to work fine if HandleCurrentScreen
points to a function that is also defined in the Game class. I've been looking for other people with this problem, but none seem to have it in cases like this.
A solution that might work is something like this:
Screen* p_currentScreen;
void Game::SetScreen(const Screen& newScreen)
{
p_currentScreen = &newScreen;
}
and then instead of calling HandleCurrentScreen
I can call p_currentScreen->Handle()
, but this seems slightly less efficient to me.
What can I do to fix this? Should I just use a pointer to a class instead of a function pointer?
Any advice is welcome.
Your error tells you what to do:
Screen::Handle': function call missing argument list; use '&Screen::Handle
You should write it as:
void Game::SetScreen(const Screen& newScreen)
{
HandleCurrentScreen = &Screen::Handle;
}
It will work only in case newScreen::handle
is a static function. But in that case you could initialize it at compile time. Otherwise HandleCurrentScreen
should be a pointer to a member function (PTMF) declared as:
void (Screen::*HandleCurrentScreen)();
Now, in order to call the function from a PTMF you need a function object as well. That makes your second solution better.
Another option is std::bind:
class Game
{
private:
std::function<void()> HandleCurrentScreen;
public:
void SetScreen(const Screen& newScreen) {
HandleCurrentScreen = std::bind(&Screen::Handle, &newScreen);
}
};