demo:
#include<iostream>
struct A { int i = 10; };
struct B : A { };
int main(){
std::cout << "decltype(&B::i) == int A::* ? " << std::boolalpha
<< std::is_same<decltype(&B::i), int A::*>::value << 'n'; //#1
A a;
std::cout << a.*(&A::i) << 'n';
std::cout << "decltype(&B::i) == int B::* ? "
<< std::is_same<decltype(&B::i), int B::*>::value << 'n'; //#2
B b;
std::cout << b.*(&B::i) << 'n';
}
代码打印
decltype(&B::i) == int A::* ? true
10
decltype(&B::i) == int B::* ? false
10
我在 [expr.unary.op]/3 中使用了这个例子,其中标准说&B::i
的类型是int A::*
,但这不是规范性的。
从你链接到的段落中,强调我的:
如果操作数是命名非静态或变体成员的限定 ID
m
某些类C
类型为T
时,结果的类型为 "指向成员的指针"T
类C
",是指定C::m
的 prvalue 。
"某些类C
"意味着它不必与限定ID提到的类相同。在这种情况下,i
是A
的成员,即使被&B::i
命名,它仍然是A
的成员。因此,&B::i
的类型是int A::*
的,您可以通过测试进行验证
std::is_same<decltype(&B::i), int A::*>::value
根据 [class.qual]/1,成员查找遵循 [class.member.lookup] 中详述的算法。正是根据那里的规则(检查成员i
来自的子对象)确定类C
。由于i
是子对象A
的成员,指向成员的指针的类被确定为A
。