a()
是非静态成员函数,因此被解释为(*this).a()
。引用自[expr.prim.general]/3的一部分:
如果一个声明声明了类X的成员函数或成员函数模板,则表达式
this
是一个类型为“指向cv限定符序列X”的prvalue,在可选的cv限定符序列和函数定义、成员声明符或声明符的结尾之间。它不应出现在可选的cv限定符序列之前,并且不应出现在静态成员函数的声明中(尽管其类型和值种类在静态成员函数中的定义与它们在非静态成员函数中相同)。
由于S :: b
没有cv限定符,所以trailing-return-type出现在可选的cv-qualifier-seq之后(在您的示例中省略),因此this
可以出现在那里,但它不能出现在之前。
this
的类型。 - T.C.this
的自由 :) - Brian Bi对@Brian的回答进行一些补充:
在第一个例子中,a()
并没有被转换为 (*this).a()
。这种转换是在[class.mfct.non-static]/3中指定的,并且仅在“可以使用this
”的上下文中发生。如果没有这种转换,由于违反[expr.prim.id]/2,代码将是非法的:
表示类的非静态数据成员或非静态成员函数的id-expression只能在以下情况下使用:
作为类成员访问的一部分([expr.ref]),其中对象表达式引用该成员的类63或从该类派生的类,或
形成成员指针([expr.unary.op]),或
如果该id-expression表示非静态数据成员,并且出现在未求值的操作数中。
使用表示非静态成员函数的id-expression a
,超出了允许的上下文范围。
没有进行类成员访问转换是重要的原因是,它使以下代码有效:
struct A {
int a;
decltype(a) b();
};
如果将decltype(a)
改为decltype((*this).a)
,那么代码就无法通过编译。
*this
在类成员访问中有一个特殊例外,即使其类型不完整也可以使用([expr.prim.this]/2):
与其他情况不同,对于类成员的访问而言,在成员函数体之外访问时,对象表达式
*this
并不要求具有完整的类型。([expr.ref])