错误:指向绑定函数的指针只能用于调用该函数

Error: a pointer to a bound function may only be used to call the function

本文关键字:函数 用于 调用 指针 绑定 错误      更新时间:2023-10-16

我一直在尝试将函数指针(类的)分配给(另一个类的)成员函数,像这样:

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

我得到这个错误:

错误C3867: 'Screen::Handle':函数调用缺少参数列表;使用'&Screen::Handle'创建指向成员

的指针

如果HandleCurrentScreen指向也在Game类中定义的函数,则似乎可以正常工作。我一直在寻找其他有这个问题的人,但似乎没有人有这样的情况。

一个可能有效的解决方案是这样的:

Screen* p_currentScreen;
void Game::SetScreen(const Screen& newScreen)
{
    p_currentScreen = &newScreen;
}

然后调用p_currentScreen->Handle()而不是HandleCurrentScreen,但这对我来说似乎效率稍低。

我能做些什么来解决这个问题?我应该只是使用一个指针到一个类,而不是一个函数指针?

欢迎提出建议

你的错误告诉你该怎么做:

Screen::Handle': function call missing argument list; use '&Screen::Handle

你应该这样写:

void Game::SetScreen(const Screen& newScreen)
{
    HandleCurrentScreen = &Screen::Handle;
}

仅在newScreen::handle是静态函数的情况下才会工作。但在这种情况下,你可以在编译时初始化它。否则,HandleCurrentScreen应该是指向成员函数(PTMF)的指针,声明为:

void (Screen::*HandleCurrentScreen)();

现在,为了从PTMF调用函数,还需要一个函数对象。这使你的第二个解决方案更好。

另一个选项是std::bind:

class Game
{
private:
    std::function<void()> HandleCurrentScreen;
public:
    void SetScreen(const Screen& newScreen) {
        HandleCurrentScreen = std::bind(&Screen::Handle, &newScreen);
    }
};

std::bind就是用来解决这类问题的:

// --- Game.h ---
#ifndef GAME_H
#define GAME_H
#include "Screen.h"
#include <functional>
class Game {
private:
    std::function<void ()> HandleCurrentScreen;
public:
    void SetScreen(const Screen& newScreen);
};
#endif

 // -- Game.cc --
#include "Game.h"
#include "Screen.h"
void Game::SetScreen(const Screen& newScreen){
   HandleCurrentScreen = std::bind( &Screen::Handle, newScreen);
}

然而,由于您的Game类只需要一个函数,因此最好将Screen类完全从Game定义中删除,并将函数直接传递给它:

#include <functional>
class Game {
public:
    typedef std::function<void ()> ScreenHandler;
private:
    ScreenHandler HandleCurrentScreen;
public:
    void SetHandle(const ScreenHandler &handle);
};
#endif
 // -- Game.cc --
#include "Game.h"
void Game::SetHandle(const ScreenHandler &handle){
   HandleCurrentScreen = handle;
}

这样,您就可以选择以您认为合适的方式构建处理程序,而不涉及Game

把函数设为静态