C++函数调用作为参数,而不是工作

问题描述:

http://pastebin.com/CsViwQFg 我使用的是被称为DragonFireSDK的SDK,并有一个名为TouchAdd(),它可以让我补充一个函数作为参数(在这种情况下功能:MoveLeft()和MoveRight的())。 唯一的问题是,如果函数是一个类(在这种情况下,播放器类),我收到以下错误:C++函数调用作为参数,而不是工作

Player *player; 

void AppMain() 
{ 
    player = new Player(20,20,10); 

    tleft = TouchAdd(0,0,180,480,player->MoveLeft,0); 
    tright = TouchAdd(180,0,180,480,player->MoveRight,0); 
} 

错误:

error C3867: 'Player::MoveLeft': function call missing argument list; use '&Player::MoveLeft' to create a pointer to member 
error C3867: 'Player::MoveRight': function call missing argument list; use '&Player::MoveRight' to create a pointer to member 
+0

您可能会发现需要静态函数(取决于我认为的接口定义) – forsvarir 2011-04-14 05:06:45

+0

TouchAdd函数的签名是什么?例如,函数的参数是什么类型? – Xeo 2011-04-14 05:06:55

tleft = TouchAdd(0,0,180,480,player->MoveLeft,0); 
tright = TouchAdd(180,0,180,480,player->MoveRight,0); 

你'不传递MoveLeftMoveRight函数的参数。我想他们是函数调用,因为你的主题的标题说,所以你必须通过参数,如果他们采取论据。

如果他们不采取说法,那么这样做:

tleft = TouchAdd(0,0,180,480,player->MoveLeft(),0); 
tright = TouchAdd(180,0,180,480,player->MoveRight(),0); 

如果他们不函数调用,而不是你想通过成员函数指针,然后执行以下操作:

tleft = TouchAdd(0,0,180,480, &Player::MoveLeft,0); 
tright = TouchAdd(180,0,180,480, &Player::MoveRight,0); 

您还需要传递该实例,以便稍后可以调用成员函数。

如果你让我们知道TouchAdd函数的签名会更好。这样我们可以更具体地回答。

+1

我相信OP正在尝试传递一个函数指针,而不是调用该函数并传递函数的返回值。 – forsvarir 2011-04-14 05:04:50

+0

@forsvarir:也许吧。这就是为什么我将这也添加到我的帖子。 – Nawaz 2011-04-14 05:07:35

+0

@Downvoter:请说明原因。只有downvote并不能帮助我纠正自己。 – Nawaz 2011-04-14 05:09:39

如果您想将函数作为参数传递,则语法为&Player::MoveLeft;,因为它不绑定到任何对象,如player

DragonFireSDK似乎想要一个“C”可调用函数,并且您试图传递一个成员函数(尽管不使用正确的语法)。我认为你需要做的是这样:

Player *player; 

extern "C" 
int PlayerMoveLeft(int id, int event, int x, int y) 
{ 
    // do something - I'm not sure what might be possible 
    // to get a pointer or a reference to the player object 
    // hopefully one or more parameters passed to this callback 
    // will have the information you need to do that 

    // or if you only have one global player, you're set - 
    // just use it 
    Player* player = /* ??? */; 

    player->MoveLeft(id, event, x, y); // or whatever needs to be passed 

    return 0; 
} 

extern "C" 
int PlayerMoveRight(int id, int event, int x, int y) 
{ 
    Player* player = /* ??? */; 

    player->MoveRight(id, event, x, y); // or whatever needs to be passed 

    return 0; 
} 


void AppMain() 
{ 
    player = new Player(20,20,10); 

    tleft = TouchAdd(0,0,180,480,PlayerMoveLeft,0); 
    tright = TouchAdd(180,0,180,480,PlayerMoveRight,0); 
} 

注意,即使一个静态成员函数往往会工作(因为没有“隐藏” this指针传递中,严格来说,你应该使用非成员extern "C"功能。

+0

正如有人在现在删除的评论中提到的那样,“id '参数可能有足够的信息来查找目标'Player'对象 - 可能通过将这些DragonFire ID的映射保存到'Player'对象。我对DragonFireSDK的了解不够多,不足以推测。 – 2011-04-14 05:35:08

由于(从here截取)的TouchAdd函数签名是

int TouchAdd(int x, int y, int width, int height, int (*callback)(int id, int event, int x, int y), int id); 

预期功能必须是自由功能,例如:

int myCallback(int id, int event, int x, int y){ 
    // do your stuff 
} 

void AppMain(){ 
    tLeft = TouchAdd(....,&myCallback,...); 
} 

不能传递一个成员函数的指针(&Player::MoveX),因为该功能需要与类(Player)的对象上被调用。所以,你需要使用一个变通为:

Player* player; 

int PlayerMoveLeft(int id, int event, int x, int y){ 
    return player->MoveLeft(id,event,x,y); 
} 

int PlayerMoveRight(int id, int event, int x, int y){ 
    return player->MoveRight(id,event,x,y); 
} 

void AppMain(){ 
    player = new Player(20,20,10); 
    tLeft = TouchAdd(...,&PlayerMoveLeft,...); 
    tRight = TouchAdd(...,&PlayerMoveRight,...); 
} 

}

好像id是被传递给回调的自定义参数。如果你只有32位目标(而且DragonFireSDK似乎只适用于iPhone,所以我猜答案是肯定的),你可以将它转换为Player *绑定到播放器实例。

int PlayerMoveLeft(int id, int event, int x, int y) 
{ 
    Player* player = reinterpret_cast<Player*>(id); 

    return player->MoveLeft(event, x, y); 
} 

int PlayerMoveRight(int id, int event, int x, int y) 
{ 
    Player* player = (Player*)id; 

    return player->MoveRight(event, x, y); 
} 

void AppMain() 
{ 
    Player* player = new Player(20,20,10); 

    tleft = TouchAdd(0,0,180,480,PlayerMoveLeft,(int)player); 
    tright = TouchAdd(180,0,180,480,PlayerMoveRight,(int)player); 
} 

即使不工作,或者你不想使用有点丑陋的类型转换,你可以随时与查找表全局或静态对象。使PlayerMoveLeft和PlayerMoveRight Player类的静态成员也可能看起来更好,我认为它应该在TouchAdd()中表现良好。