成员函数指针

Ced*_* H. 16 c++ member-function-pointers member-pointers

如果C++ FAQ Lite中的以下内容为真:"函数名称衰减到指向函数的指针"(因为数组名称衰减为指向其第一个元素的指针); 为什么我们必须加入&符号?

typedef  int (Fred::*FredMemFn)(char x, float y);
FredMemFn p = &Fred::f;
Run Code Online (Sandbox Code Playgroud)

而不只是:

typedef  int (Fred::*FredMemFn)(char x, float y);
FredMemFn p = Fred::f;
Run Code Online (Sandbox Code Playgroud)

在第二种情况下,Fred :: f是一个函数,可以衰减到指向该函数的指针.

我希望这个问题不是那么愚蠢.

Arm*_*yan 17

原始答案:

因为成员函数不是函数而成员函数指针不是函数指针.因此,腐烂规则不适用.

此外,C++中有函数类型,但不是成员函数类型.因此,您可以在需要指向函数的位置使用函数,但是您不能使用成员函数,因为没有这样的东西,只有指向成员函数的指针.你的例子中的f是一个函数.另一方面,Fred :: f是......好吧,没什么.

此外,我认为"功能的名称可能会腐烂......".不,名称不能做任何事情,函数类型的左值可以隐式转换为指向函数的指针,就重载解析而言,这是一个身份转换

编辑以澄清我的答案:

C++中的每个表达式都有一个类型和值.偶尔可以将一种类型的值转换为另一种类型的值.对这些转换进行排序,以使一次转换更好,另一次转换主要用于函数重载解析.

其中一种转换类型称为左值到右值转换.当左值出现在需要右值的上下文中时,将发生此转换.通常这种转换什么都不做,例如:

int i = 4, j = 5;
i = j;
Run Code Online (Sandbox Code Playgroud)

在第二行j上是一个左值,但这里需要一个右值,因此j被转换为右值.但这不是一个可观察到的转换,是吗?但是有些情况下可以观察到左值到右值的转换.也就是说,n T数组的左值可以转换为类型的右值,T*其值是数组的第一个元素的地址,以及 类型为"带签名S的函数"的左值,类型为"指向函数的指针"的右值签名S",其值是函数的地址

这意味着当我们将函数赋值给函数指针时,函数lvalue会隐式转换为它的地址.

void f() {}
void (*p) () = f; //f is converted to rvalue
Run Code Online (Sandbox Code Playgroud)

f是一个表达式并且有一个类型.f的类型是void()

C++中没有这样的类型作为一个member-function 指向成员函数的指针,而不是成员函数本身.我当然在谈论非静态功能.静态函数的工作方式与普通函数相同,也就是说,您不必编写&X::f,而是可以编写X::f 为什么?因为X :: f具有类型函数并且发生上述转换.但是,如果f是非静态的,那么X :: f的类型是什么?哦,是的,它没有类型,因此不是表达式,因此没有值,因此该值不能转换为任何值.

引用标准:5.3.1子句3只有当使用显式&时,才会形成指向成员的指针,并且其操作数是未括在括号中的qualified-id.[注意:也就是说,表达式&(qualified-id),其中qualified-id括在括号中,不形成"指向成员的指针"类型的表达式.也不是qualified-id,因为没有隐式转换从非静态成员函数的限定id到类型"指向成员函数的指针",因为从函数类型的左值到类型"指向函数的指针"(4.3).即使在unqualified-id类的范围内,也不是&nonqualified-id指向成员的指针.]

希望这更清楚......

  • 哦,我错了!我确信`typeid(Fred :: FredMemFn)`不能编译.从标准引用:一元`&`运算符的结果是指向其操作数的指针.操作数应为左值或*qualified-id*.如果操作数是*qualified-id*命名一个类型为"T"的类`C`的非静态成员`m`,则结果具有类型"指向`T`类的类`C`成员的指针" (2认同)
  • 我很震惊,这个答案到目前为止只有1(我的)upvote ...这是一个很好的答案! (2认同)
  • @Armen Tsirunyan:谢谢你的回答! (2认同)
  • @ArmenTsirunyan 不!仅在某些有限情况下才允许使用表示非静态成员函数的 _id-expression_。请阅读 §5.1/10(对于 C++03)或 §5.1/12(对于 C++11)。 (2认同)