名字查找
有限制的名字查找
有限制的名字查找是指名字出现在“::”(作用域解析符)的右面。有限制的名字可能包括以下几种:
- 类成员
- 名字空间成员(可能包括另一个空间)
- enumerator
如果“::”左面什么都没有,查找会从全局命名空间查找(或者通过使用using 加入的命名空间)。
#include <iostream>
int main(){
class std{
public:
};
std::cout<<"*****"<<std::endl; // error: cout isn't a member of "main()::std"
::std::cout<<"......."<<::std::endl; //Ok: ::std find the namespace std
return 0;
}
在“::”右面的名字进行查找之前,会先查找"::"左面的名字。“::”左面名字的查找,可能是有限制的名字查找,或者没有限制的名字查找,关键取决于是否有操作符"::"。"::"左面的名字查找,只会从class, namespace ,enumeration, templates中查找(不会从普通变量中查找)。
#include <iostream>
int main(){
int std;
std::cout<<"*****"<<std::endl; // correct: only search from class,namespace, template,enumeration
::std::cout<<"......."<<::std::endl;
return 0;
}
如果有限制的名字被用到声明符中,则在同一个声明符中的在这个名字之后的所有名字都会在“与这个名字相同的限制下查找”,而,在这个名字之前的名字查找照旧。
class X { };
constexpr int number = 100;
class C {
class X { };
static const int number = 50;
static X arr[number];
};
X C::arr[number], brr[number]; // Error
// Every name in the declarator "C::arr[number]" after "C::arr"
// is looked up within C::, but the names before C::arr are unaffected,
// The names in the second declarator ("brr[number]") are also unaffected
// equivalent to:
// "::X C::arr[C::number], brr[::number]"
C::X C::arr[number], brr[number]; // Compiles, size of arr is 50, size of brr is 100
enumerator查找:
如果在"::"左面的名字查找中遇到enumeration,必须要保证"::"右面的enumerator包含在enumeration中,否则,程序就会undefined。
class memeber 查找:
如果"::"左面是class,则右面的名字查找,会从class的作用域或者子类的作用域中查找。
struct B { virtual void foo(); };
struct D : B { void foo() override; };
int main()
{
D x;
B& b = x;
b.foo(); // calls D::foo (virtual dispatch)
b.B::foo(); // calls B::foo (static dispatch)
}
命名空间成员查找:
如果"::"左面是一个命名空间,或者"::"左面什么都没有(全局命名空间),"::"右面的名字在该命名空间中查找。除了以下特殊情况,模板参数:
namespace N {
template<typename T> struct foo {};
struct X {};
}
N::foo<X> x; // error: X is looked up as ::X, not as N::X
例子说明命名空间成员查找:
namespace B{
using namespace X;
inline namespace BB{
}
}
namespace C{
using namespace Y;
inline namespace CC{
}
}
namespace A{
inline namespace AA{
}
using namespace B;
using namespace C;
}
A::f();
A::f的查找规则为:
- 先在命名空间A和A的inline命名空间AA中查找,如果找到,则返回(返回并不表示正确,这里的返回只是找到了名字,如果名字与使用的类型不符,或函数不符,则编译错误);如果没有找到,则进行下一步。
- 在命名空间B和C中查找(包括其inline namespace BB and CC),如果找到,有重复定义报错,类型不符,报错。如果没找到,继续下一步。
- 在X 和 Y中查找。
可以抽象namespace的查找,为一棵树,名字查找方法为层次遍历,如果在某一层中,查找到,不管正确与否,也不再继续查找;如果没有查找到,继续查找下一层。
特例,允许通过不同路径找到同一个声明:
namespace A { int a; }
namespace B { using namespace A; }
namespace D { using A::a; }
namespace BD {
using namespace B;
using namespace D;
}
void g()
{
BD::a++; // OK: finds the same A::a through B and through D
}
无限制的名字查找
无限制的名字查找是指,需要查找的名字没有出现在"::"后面。
File Scope
如果名字在file scope 使用(global scope),在名字使用前,要在global scope 查找。
int n = 1; // declaration of n
int x = n + 1; // OK: lookup finds ::n
int z = y - 1; // Error: lookup fails
int y = 2; // declaration of y
Namespace Scope
如果名字出现在自己声明的命名空间里,在任何函数和类之外。名字查找顺序为:
- 该命名空间,名字出现前的部分。
- 包含该命名空间的命名空间的,名字出现前的部分(using 命名空间,在改名字出现的部分)
- 直到,全局命名空间。
注意,这里的名字查找与上面的命名空间成员查找,一样,也是通过构造��,层次遍历,得到。
在命名空间以外的定义
对于用来定于命名空间内变量的名字,无论放在命名空间内,或放在命名空间之外,查找规则,都是一样的。
namespace X {
extern int x; // declaration, not definition
int n = 1; // found 1st
};
int n = 2; // found 2nd.
int X::x = n; // finds X::n, sets X::x to 1
非成员函数定义
如果一个名字,出现在函数定义中,或者在函数体中,或者作为默认参数。这个函数可以是global namespace 中的函数,或者是user-declared namespace的函数。查找规则是,先在函数体中查找,然后,再到命名空间中查找。
namespace A {
namespace N {
void f();
int i=3; // found 3rd (if 2nd is not present)
}
int i=4; // found 4th (if 3rd is not present)
}
int i=5; // found 5th (if 4th is not present)
void A::N::f() {
int i = 2; // found 2nd (if 1st is not present)
while(true) {
int i = 1; // found 1st: lookup is done
std::cout << i;
}
}
// int i; // not found
namespace A {
namespace N {
// int i; // not found
}
}
class定义
namespace M {
// const int i = 1; // never found
class B {
// const const int i = 3; // found 3nd (but later rejected by access check)
};
}
// const int i = 5; // found 5th
namespace N {
// const int i = 4; // found 4th
class Y : public M::B {
// static const int i = 2; // found 2nd
class X {
// static const int i = 1; // found 1st
int a[i]; // use of i
// static const int i = 1; // never found
};
// static const int i = 2; // never found
};
// const int i = 4; // never found
}
// const int i = 5; // never found
成员函数定义
class B {
// int i; // found 3rd
};
namespace M {
// int i; // found 5th
namespace N {
// int i; // found 4th
class X : public B {
// int i; // found 2nd
void f();
// int i; // found 2nd as well
};
// int i; // found 4th
}
}
// int i; // found 6th
void M::N::X::f()
{
// int i; // found 1st
i = 16;
// int i; // never found
}
namespace M {
namespace N {
// int i; // never found
}
}