c++ 名字查找

名字查找

有限制的名字查找


有限制的名字查找是指名字出现在“::”(作用域解析符)的右面。有限制的名字可能包括以下几种:

  • 类成员
  • 名字空间成员(可能包括另一个空间)
  • 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的查找规则为:

  1. 先在命名空间A和A的inline命名空间AA中查找,如果找到,则返回(返回并不表示正确,这里的返回只是找到了名字,如果名字与使用的类型不符,或函数不符,则编译错误);如果没有找到,则进行下一步。
  2. 在命名空间B和C中查找(包括其inline namespace BB and CC),如果找到,有重复定义报错,类型不符,报错。如果没找到,继续下一步。
  3. 在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

如果名字出现在自己声明的命名空间里,在任何函数和类之外。名字查找顺序为:

  1. 该命名空间,名字出现前的部分。
  2. 包含该命名空间的命名空间的,名字出现前的部分(using 命名空间,在改名字出现的部分)
  3. 直到,全局命名空间。

注意,这里的名字查找与上面的命名空间成员查找,一样,也是通过构造��,层次遍历,得到。

在命名空间以外的定义

对于用来定于命名空间内变量的名字,无论放在命名空间内,或放在命名空间之外,查找规则,都是一样的。

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
  }
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值