C++函数指针调用不在作用域内

8

我已经花了三个小时尝试找出我的问题所在。我只需要其他人帮我看一下,我已经尝试了我能想到的一切,甚至包括各种随机排列组合,试图让编译器告诉我有用的信息。

现在我在这里:

代码:

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

当我调用 "targets[0]->*OnFire()" 时,出现错误,指出它在此范围内未声明。 对于我来说,必须在villain构造函数中定义 "OnFire",并使用 "&villain ::" 定义它,感觉很奇怪,但我找到的所有信息都表明必须以这种方式完成,否则会产生一堆错误。

调用属于 targets [0] 的 *OnFire()指针的正确语法是什么?


不需要使用解引用运算符,只需调用 targets[0]->OnFire() - user3235832
@wiily 对于普通指针来说没问题,但对于成员指针就不行了。 - Alan Stokes
为什么要声明一个数组的指针?声明一个数组已经意味着你在声明它的第一个元素的指针。 - merosss
所需的语法至少是完全明确的,尽管有些烦人。 - Alan Stokes
1
@meross 这是一个指针数组。而一个数组并不是指针,即使它可以衰减为一个指针。 - Alan Stokes
4个回答

5
调用成员函数指针的语法相当糟糕。以下是正确的语法:
if ((targets[0]->*(targets[0]->OnFire))() == true)

这真是太丑了。这就是为什么Parashift C++ FAQ关于调用成员函数指针的页面建议定义一个宏来实现这个目的 - 请注意,这些页面的作者不喜欢使用宏。

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

...

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

要么使用宏,要么像sehe的回答中所述一样使用std::function

天啊,它编译通过了。虽然丑陋,但它能用。非常感谢! - user3542913
1
@user3542913,让我给你一些父亲式的建议。当你想写出这样的代码时:不要这么做。而且:不要使用邪恶的宏来解决问题。我的答案展示了可读性更好的版本,就是这个:if ((v.*ptmf)())... - sehe
嗯,除非你在下面更改了答案,而我还没有机会尝试新的修订版。旧版本对我无效。 - user3542913
@sehe,有很多C++项目一直停留在C++03时代,不允许使用Boost。在那个世界里,调用成员函数指针是很困难的。正确的语法非常丑陋(我之前就说过了!),宏也不是一个坏的替代方案。 - David Hammen
1
@David std::function 是 TR1 的一部分。是的,即使没有宏定义,也可以使用 我的答案展示在 Coliru 上 Live (纯粹的 C++03,不需要 TR1)。 - sehe

2

更改

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

to

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

由于函数调用运算符 () 的优先级高于 ->*,因此第一种形式被解释为:

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

正如您所看到的,这不是您想要的。


尝试了这个,不幸的是返回了相同的错误。 - user3542913

1
没有所谓的“正确语法”。这将是可怕的(见下文)。
使用std::function代替:
#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;
}

与指向成员函数的指针相比,这个方法如下:
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;
}

@AlanStokes 看起来我不理解你想说什么。顺便说一下,我测试所有的代码 :/ - sehe
啊,抱歉,我误解了你的意思。错误完全是我的责任。 - Alan Stokes
第一个例子返回一个错误:“命名空间'std'中的'function'不是一个类型”。 - user3542913
@pmr 这是一个选择。如果您不绑定对象引用,您将可以像 OP 一样进行选择,因此更接近原始代码并且更灵活。 - sehe
@AlanStokes 哦,啊哈,我完全错过了第二个问题。嗯,那里几乎不需要它 ;) - sehe
显示剩余7条评论

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接