C++的Name lookup之qualified name lookup

转载注明来源地址:http://blog.csdn.net/lastsweetop/article/details/49427735

1. 简介

C++中Name lookup的过程就是一个通过name找到对应申明的过程。对于函数来说,name lookup可能会匹配出很多个申明,然后如果是函数再通过Argument-dependent lookup去查找,如果是函数模板那么通过Template argument deduction去查找,最后一步通过overload resolution去解决。 

name lookup分为两种,qualified name lookup和unqualified name lookup,第一个name的左边是否还有::符号。

2. qualified name lookup 

一个Qualified name出现在::的右边,它可以包括:类成员(方法,类型,模板等);命名空间成员(另一个命名空间);枚举

规则如下:

::左边如果没有其他元素的话,那么默认使用顶级命名空间,示例如下:

#include <iostream>
int main()
{
  struct std{};
  std::cout << "fail\n"; // Error: unqualified lookup for 'std' finds the struct
  ::std::cout << "ok\n"; // OK: ::std finds the namespace std
}
namelookup的顺序是从左到右的,::左边的元素只会被当做命令空间,类,枚举,模板,示例如下:

struct A {
  static int n;
};
int main() {
  int A;
  A::n = 42;    // OK: unqualified lookup of A to the left of :: ignores the variable
  A b;          // error: unqualified lookup of A finds the variable A
}
如果一个qualified name作为一个一个声明,那么在它之后的所有相同申明的name的lookup都会和它一样,在他之前的除外。

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
如果::的右边是一个析构函数,那么这个析构函数的name lookup将会和::左边的name lookup保持一致。

struct C { typedef int I; };
typedef int I1, I2;
extern int *p, *q;
struct A { ~A(){}; };
typedef A AB;
int main() {
    p->C::I::~I(); // the name I after ~ is looked up in the same scope as I before ::
    // (that is, within the scope of C, so it finds C::I)
    q->I1::~I2();  // The name I2 is looked up in the same scope as I1
    // that is, from the current scope, so it finds ::I2
    AB x;
    x.AB::~AB(); // The name AB after ~ is looked up in the same scope as AB before ::
    // that is, from the current scope, so it finds ::AB
}
如果::的左右两边都是相同的类名,那么他只能被当做一个构造函数。但是当使用Elaborated type specifier时后面的函数就会被忽略掉。

struct A { A(); };
struct B : A { B(); };
A::A() { } // A::A names a constructor, used in a declaration
B::B() { } // B::B names a constructor, used in a declaration
B::A ba;   // B::A names the type A (looked up in the scope of B)
A::A a;    // Error, A::A does not name a type
 
struct A::A a2; // OK: lookup in elaborated type specifier ignores functions
                // so A::A simply names the class A as seen from within the scope of A
                // (that is, the injected-class-name)

qualified name lookup可以用来访问被嵌套或者派生隐藏的类成员

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)
}
当::的左边指定了命名空间,或者::左边没有name(使用顶级命名空间),::的右边就使用该命名空间,除了下面这种情况,即name被用作模板参数。

namespace N {
    template<typename T> struct foo {};
    struct X {};
}
N::foo<X> x; // error: X is looked up as ::X, not as N::X
在命名中间嵌套引用中,Qualified name lookup递归执行,先在第一层中lookup,如果没有就在引用的命名空间中lookup,一直递归下去:

int x;
namespace Y {
    void f(float);
    void h(int);
}
namespace Z {
    void h(double);
}
namespace A {
    using namespace Y;
    void f(int);
    void g(int);
    int i;
}
namespace B {
    using namespace Z;
    void f(char);
    int i;
}
namespace AB {
    using namespace A;
    using namespace B;
    void g();
}
void h()
{
    AB::g();  // AB is searched, AB::g found by lookup and is chosen AB::g(void)
    // (A and B are not searched)
    AB::f(1); // First, AB is searched, there is no f
    // Then, A, B are searched
    // A::f, B::f found by lookup (but Y is not searched so Y::f is not considered)
    // overload resolution picks A::f(int)
    AB::x++;    // First, AB is searched, there is no x
    // Then A, B are searched. There is no x
    // Then Y and Z are searched. There is still no x: this is an error
    AB::i++;  // AB is searched, there is no i
    // Then A, B are searched. A::i and B::i found by lookup: this is an error
    AB::h(16.8);  // First, AB is searched: there is no h
    // Then A, B are searched. There is no h
    // Then Y and Z are searched.
    // lookup finds Y::h and Z::h. Overload resolution picks Z::h(double)
}
而且允许存在相同的申明

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
}


  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值