C++ Primer 学习笔记_93_用于大型程序的工具 --命名空间[续2]

用于大型程序的工具

--命名空间[2]



五、类、命名空间和作用域

名字的可见性穿过任意嵌套作用域,直到引入名字的块的末尾。

对命名空间内部使用的名字的查找遵循常规C++查找规则:当查找名字的时候,通过外围作用域外查找。对命名空间内部使用的名字而言,外围作用域可能是一个或多个嵌套的命名空间,最终以全包围的全局命名空间结束只考虑已经在使用点之前声明的名字,而该使用仍在开放的块中:

namespace A
{
int i;
namespace B
{
int i;
int j;
int f1()
{
    int j;
    return i;
}
}

int f2()
{
    return j;   //Error
}

int j = i;
}

用非常相似的方式确定类成员定义中使用的名字,只有一个重要区别:如果名字不是局部于成员函数的,就试着在查找更外层作用域之前在类成员中确定名字

当类包在命名空间中的时候:首先在成员中找,然后在类(包括基类)中找,再在外围作用域中找,外围作用域中的一个或多个可以是命名空间:

namespace A
{
int i;
int k;
class C1
{
public:
    C1():i(0),j(0) {}   //C1::i,C1::j
    int f1()
    {
        return k;   //A::k
    }
    int f2()
    {
        return h;   //Error
    }
    int f3();

private:
    int i;
    int j;
};

int h = i;  //A::i
}

int A::C1::f3()
{
    return h;   //A::h
}

除了定义成员之外,总是向上查找作用域:名字在使用之前必须声明

【提示】

可以从函数的限定名推断出查找名字时所检查作用域的次序,限定名以相反次序指出被查找的作用域

限定符A::C1::f3指出了查找类作用域和命名空间作用域的相反次序,首先查找函数 f3的作用域,然后查找外围类C1的作用域。在查找包含f3定义的作用之前,最后查找命名空间A的作用域。



1、实参相关的查找与类类型形参

    std::string s;
    getline(std::cin,s);

它给出了屏蔽命名空间规则的一个例外:

类类型形参(或类类型指针及引用形参)的且与类本身定义在同一命名空间中的函数(包括重载操作符),在用类类型对象(或类类型的引用及指针)作为实参的时候是可见的。

当编译器看到getline函数的使用

	 getline(std::cin, s); 

的时候,在当前作用域,包含调用的作用域以及定义cin的类型和 string类型的命名空间中查找匹配的函数。因此,在命名空间std中查找并找到由string类型定义的getline函数

函数具有类类型形参就使得函数可见,其原因在于,允许无须单独的 using声明就可以使用概念上作为类接口组成部分的非成员函数。能够使用非成员操作对操作符函数特别有用

    std::string s;
    cin >> s;   //在有些编译器上还未实现,如g++

如果没有查找规则的这个例外,我们将必须编写下面二者之一:

    using std::operator>>;
    std::operator>>(std::cin,s);



2、隐式友元声明与命名空间

当一个类声明友元函数的时候,函数的声明不必是可见的。如果不存在可见的声明,那么,友元声明具有将该函数或类的声明放入外围作用域的效果。如果类在命名空间内部定义,则没有另外声明的友元函数在同一命名空间中声明

namespace A
{
class C
{
    friend void f(const C &);   //f成为命名空间A的一员
};
}

因为该友元接受类类型实参并与类隐式声明在同一命名空间,所以使用它时可以无须使用显式命名空间限定符:

void f2()
{
    A::C cobj;
    f(cobj);
}

C++ Primer 学习笔记_93_用于大型程序的工具 --命名空间[续2],古老的榕树,5-wow.com

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。