简体   繁体   中英

C++ Function call as a parameter, not working

http://pastebin.com/CsViwQFg I'm using an SDK known as DragonFireSDK and there's a function called TouchAdd() that let's me add a function as a parameter (in this case: MoveLeft() and MoveRight()). The only problem is, if the function is in a class (in this case, the Player class), I get the following errors:

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

The error:

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

If you want to pass function as a parameter then syntax is &Player::MoveLeft; as it is not bound to any object such as player .

The DragonFireSDK appears to want a "C" callable function and you're trying to pass a member function (though not using the right syntax). I think you'll need to do something like:

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

Note that even though a static member function will often work (since there's no 'hidden' this pointer passed in, strictly speaking you should use non-member extern "C" functions.

Since the function signature of TouchAdd (taken from here ) is

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

the expected function must be a free function, eg:

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

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

You can't pass a member function pointer ( &Player::MoveX ), since that function needs to be called on an object of that class ( Player ). So you need to use a work-around for that:

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

}

It seems like id is the custom parameter that gets passed to the callback. If you only have 32-bit targets (and it seems like DragonFireSDK is meant only for iPhone, so I guess the answer is yes), you can cast it to Player* to bind to the player instance.

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

Even if that doesn't work, or you don't want to use kinda-ugly type casts, you can always have a global or static object with lookup tables. Making PlayerMoveLeft and PlayerMoveRight static members of the Player class may also look nicer, and I think it should play well with TouchAdd().

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

You're not passsing arguments to MoveLeft and MoveRight functions. I suppose they're function call as the title of your topic says, so you must pass arguments as well IF they take arguments.

If they're don't take argument, then do this:

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

If they're NOT function calls, instead you want to pass the member function pointers, then do this:

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

You also need to pass the instance so that member functions can be invoked later on.

It would be better if you let us know the signature of TouchAdd function. So that we can answer more specifically.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM