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

时间:2014-07-21 19:20:14

标签: c++ member-function-pointers member-functions

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

--- 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;
}

然后我可以拨打HandleCurrentScreen而不是拨打p_currentScreen->Handle(),但这似乎对我来说效率稍差。

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

欢迎任何建议。

2 个答案:

答案 0 :(得分:3)

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

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

答案 1 :(得分:0)

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