名字查找
来自cppreference.com
名字查找,是当程序中出现一个名字时,将其与引入它的声明联系起来的过程。
例如,为编译 std::cout << std::endl;,编译器进行了:
- 名字
std
的无限定的名字查找,找到了头文件<iostream>
中的命名空间 std 的声明 - 名字
cout
的有限定的名字查找,找到了命名空间std
中的一个变量声明 - 名字
endl
的有限定的名字查找,找到了命名空间std
中的一个函数模板声明 - 名字
operator <<
的实参依赖查找,找到了命名空间std
中的多个函数模板声明;和名字std::ostream::operator<<
的有限定名字查找,找到了std::ostream
类中的多个成员函数声明
对于函数和函数模板的名字,名字查找可以将同一个名字和多个声明联系起来,而且可能从实参依赖查找中得到额外的声明。还会进行模板实参推导,并将声明的集合交给重载决议,由它选择所要使用的那个声明。成员访问的规则只会在名字查找和重载解析之后才被考虑,如果适用的话。
对于其他所有名字(变量,命名空间,类等等)的,名字查找如果将同一个名字和多个声明联系起来就需要它们都声明同一个实体,否则程序只有在只产生单个声明的情况下才能编译。对某个作用域中的名字进行查找将寻找到该名字的所有声明,但有一种例外,被称作 “struct hack” 或“类型/非类型名字隐藏”:同一作用域中,某个名字的一些出现可以代表非 typedef 的 class/struct/union/enum 声明,而其他出现要么全都代表同一个变量、非静态数据成员或者枚举项,要么全都代表可能重载的函数或函数模板名。此情况下无错误,但类型名在查找中被隐藏(代码必须用详述类型说明符来访问它)。
查找的类型
如果名字紧跟在作用域解析运算符 ::
,或可能跟在 ::
之后的消歧义关键词 template
的右侧,参见
否则,请参见
- (其中对于函数名,还包括实参依赖查找)
缺陷报告
下列更改行为的缺陷报告追溯地应用于以前出版的 C++ 标准。
缺陷报告 | 应用于 | 出版时的行为 | 正确行为 |
---|---|---|---|
CWG 2063 | C++98 | “struct hack” 无法应用于类作用域(破坏了与 C 的兼容性) | 可以应用 |
CWG 2218 | C++98 | 对函数(模板)以外的名字的查找不能与多个声明关联,即使它们都声明同一个实体 | 此时可以关联 |