Question

I have spent the last 3 hours trying to figure out what I am doing wrong. I just need some other eyes on this, I have tried everything I can think of, even various random permutations in an attempt to get the compiler to tell me something useful.

Here is where I am at now:

Code:

class villain
{
public:
   villain();
   //lots of other stuff
   bool Type1EnemyBlasts();
   bool Type2EnemyBlasts();
   bool (villain::*OnFire)();
};

villain::villain()
{
    //lots of other stuff
    OnFire = &villain::Type1EnemyBlasts;
}

main
{
    //lots and lots of other stuff
    villain *targets[100];
    targets[0] = new villain();
    if(targets[0]->*OnFire() == true)
    {
         //do stuff
    }
}

The error occurs when I call "targets[0]->*OnFire()", where it states that it is not declared in this scope. It feels weird to me that I have to define "OnFire" with "&villain::" when it is being defined inside the villain contructor, but all the information I have found suggests that it must be done this way, and indeed it churns up a whole plethora of errors if I try otherwise.

What is the proper syntax for calling the *OnFire() pointer that belongs to targets[0]?

Was it helpful?

Solution

The syntax for calling a pointer to member function is rather atrocious. Here's the correct syntax:

if ((targets[0]->*(targets[0]->OnFire))() == true)

That is downright ugly. This is why the Parashift C++ FAQ page on calling pointers to member functions recommends defining a macro for this purpose -- and note that the author of those pages dislikes macros.

#define CALL_MEMBER_FN(object,ptrToMember)  ((object).*(ptrToMember))

...

 if (CALL_MEMBER_FN(*targets[0],targets[0]->OnFire)() == true)

Either use a macro or use a std::function as described in sehe's answer.

OTHER TIPS

Change

if(targets[0]->*OnFire() == true)

to

if((targets[0]->*(targets[0]->OnFire))() == true)

Since the function call operator, (), has higher precedence than ->*, the first form is interpreted as:

if(targets[0]->*(OnFire()) == true)

which, as you can see, is not what you want.

There is no "proper syntax". It would be atrocious (see below)

Use a std::function instead:

#include <functional>

struct villain
{
    villain();
    //lots of other stuff
    bool Type1EnemyBlasts() {return true;}
    bool Type2EnemyBlasts() {return false;}
    std::function<bool(villain&)> OnFire;
};

villain::villain()
{
    OnFire = &villain::Type1EnemyBlasts;
}

int main()
{
    villain *targets[100];
    targets[0] = new villain();
    villain& v = *targets[0];

    if (v.OnFire(v))
    {
        return 1;
    }

    return 0;
}

Contrast with the pointer-to-member-function recipe:

struct villain
{
    villain();
    //lots of other stuff
    bool Type1EnemyBlasts() {return true;}
    bool Type2EnemyBlasts() {return false;}
    bool (villain::*OnFire)();
};

villain::villain()
{
    //lots of other stuff
    OnFire = &villain::Type1EnemyBlasts;
}

int main()
{
    //lots and lots of other stuff
    villain *targets[100];
    targets[0] = new villain();
    villain& v = *targets[0];

    if ((v.*v.OnFire)())
    {
        return 1;
    }

    return 0;
}

Try: (targets[0]->*OnFire)()

This has some great information on function pointers: http://www.newty.de/fpt/fpt.html#defi

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top