33

我发现了一些有趣的东西。错误消息说明了一切。在获取非静态成员函数的地址时不允许括号的原因是什么?我在 gcc 4.3.4 上编译它。

#include <iostream>

class myfoo{
    public:
     int foo(int number){
         return (number*10);
     }
};

int main (int argc, char * const argv[]) {

    int (myfoo::*fPtr)(int) = NULL;

    fPtr = &(myfoo::foo);  // main.cpp:14

    return 0;

}

错误:main.cpp:14:错误:ISO C++ 禁止使用不合格或带括号的非静态成员函数的地址来形成指向成员函数的指针。说'&myfoo::foo'

4

2 回答 2

29

从错误消息来看,您似乎不允许使用带括号的表达式的地址。建议你重写

fPtr = &(myfoo::foo);  // main.cpp:14

fPtr = &myfoo::foo;

这是由于规范的一部分(§5.3.1/3)读取

仅当使用显式 & 并且其操作数是未包含在括号中的限定 ID 时,才会形成指向成员的指针[...]

(我的重点)。我不确定为什么这是一个规则(直到现在我才真正知道这一点),但这似乎是编译器所抱怨的。

希望这可以帮助!

于 2011-08-20T19:44:04.567 回答
16

想象一下这段代码:

struct B { int data; };
struct C { int data; };

struct A : B, C {
  void f() {
    // error: converting "int B::*" to "int*" ?
    int *bData = &B::data;

    // OK: a normal pointer
    int *bData = &(B::data);
  }
};

如果没有括号的技巧,您将无法直接将指针指向 B 的数据成员(您将需要基类强制转换和带有this- 不好的游戏)。


来自 ARM:

请注意,必须显式使用地址运算符来获取指向成员的指针;没有隐式转换......如果有,我们将在成员函数的上下文中产生歧义......例如,

void B::f() {
    int B::* p = &B::i; // OK
    p = B::i; // error: B::i is an int
    p = &i; // error: '&i'means '&this->i' which is an 'int*'

    int *q = &i; // OK
    q = B::i; // error: 'B::i is an int
    q = &B::i; // error: '&B::i' is an 'int B::*'
}

IS 只是保留了这个 pre-Standard 概念,并明确提到括号使它不会得到指向成员的指针。

于 2011-08-21T13:42:30.673 回答