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

Posted

技术标签:

【中文标题】错误:指向绑定函数的指针只能用于调用函数【英文标题】:Error: a pointer to a bound function may only be used to call the function 【发布时间】:2014-07-21 19:20:14 【问题描述】:

我一直在尝试将(一个类的)函数指针分配给(另一个类的)成员函数,如下所示:

--- 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,但这对我来说似乎效率稍低。

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

欢迎任何建议。

【问题讨论】:

C++ 不是后期绑定语言。它绝对不是为了让您能够在运行时覆盖 vtable 而设计的。你的第二种方法是应该怎么做的。 @aruisdante 要么我不理解代码,要么我不理解您的评论。这里没有 vtable。 也许我读错了代码/描述,但看起来 OP 试图通过赋值覆盖类的方法在运行时解析的内容。类似于你可以在 python 中执行instance.FUNCTION_NAME = NEW_FUNCTION,其中FUNCTION_NAME 是一个类方法,NEW_FUNCTION 是一个可调用的,现在任何时候代码的任何其他部分称为instance.FUNCTION_NAME() 他们实际上会调用NEW_FUNCTION. @didierc 这有什么帮助? HandleCurrentScreen 应该是void (Screen::*HandleCurrentScreen)(),但这对你没有什么好处,因为你仍然需要一个Screen 实例(或其中的派生)在调用时连接到它。你的 intent 并不完全清楚(为什么你觉得你首先需要一个指向成员的指针,而不是你的第二个选项,这似乎是你所需要的)。 【参考方案1】:

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

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只存在于C++11中。如果您使用的是早期编译器,则必须使用 boost::bind,这是 std::bind 的灵感来源。【参考方案2】:

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

【讨论】:

【参考方案3】:

只要制作任何静态函数即可。

【讨论】:

正如目前所写,您的答案尚不清楚。请edit 添加其他详细信息,以帮助其他人了解这如何解决所提出的问题。你可以找到更多关于如何写好答案的信息in the help center。 没有别的事可做。你想要一部纪录片吗?

以上是关于错误:指向绑定函数的指针只能用于调用函数的主要内容,如果未能解决你的问题,请参考以下文章

Error:指向绑定函数的指针只能用于调用函数

从指向对象的指针调用成员函数指针时调用错误的函数

存储指向成员函数的指针不适用于 clang++

基类指针指向派生类对象&派生类指针指向基类对象

Javscript 基础

指向类方法的函数指针作为参数