我发现了一些有趣的东西。错误消息说明了一切。在获取非静态成员函数的地址时不允许使用括号的原因是什么?我在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 ++禁止获取非限定或带括号的非静态成员函数的地址,以形成指向成员函数的指针。说'&amp; myfoo :: foo'
答案 0 :(得分:27)
从错误消息中,您似乎不允许获取带括号的表达式的地址。这表明你重写了
fPtr = &(myfoo::foo); // main.cpp:14
到
fPtr = &myfoo::foo;
这是由于规范的一部分(§5.3.1/ 3)读取
指向成员的指针仅在显式&amp;使用它的操作数是一个合格的id 没有括在括号中 [...]
(我的重点)。我不确定为什么这是一个规则(直到现在我才真正知道这一点),但这似乎是编译器所抱怨的。
希望这有帮助!
答案 1 :(得分: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:
请注意,必须明确使用address-of运算符来获取指向成员的指针;没有隐式转换......如果有,我们会在成员函数的上下文中产生歧义......例如,
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只保留了这个标准前的概念,并明确提到括号使得你不会得到指向成员的指针。