声明区域(declaration region)

声明在函数外面的全局变量的声明区域为其声明所在的文件;声明在函数中的变量的声明区域为其声明所在的代码块{...}

潜在作用域(potential scope)

变量的潜在作用域从声明开始到其声明区域的结尾。

作用域(scope)

变量的可见范围。在变量名为item的潜在作用域内的一个嵌套代码块中又声明了同名的变量item,那么在这个嵌套代码块中原变量item被隐藏不可见。

名称空间(namespace)

一个可以声明名称的空间。

命名空间的特点

  1. 一个名称空间中的名称不会和另一个名称空间中同名的名称发生冲突。(可解决名称空间(命名污染)问题)
  2. 允许程序的其他部分使用名称空间中声明的内容。

关键字namespace 创建名称空间

//两个内容名称相同的名称空间
namespace Shane{
    string name = "Shane";
    int age;
    double score;
    void get_other();
    int num;
}
namespace John{
    string name = "John";
    int age;
    double score;
    void get_other();
    int num;
}
//名称空间的嵌套
namespace Student{
    int total_num = 2;
    namespace Shane{
        int num = 1;
    }
    using Johm::num;
    num = 2;
}
//全局名称空间:没有放入名称空间的全局变量会被隐式地放入到全局名称空间中
string name = "sheng";

作用域限定符:: 访问给定名称空间中的内容

//名称空间内容的访问
Shane::age = 23;
John::score = 99;
Shane::get_other();
std::cout<<Student::Shane::num;

//一个例子
using namespace Shane;
string name = "sheng";//全局作用域中定义的名字被隐式地添加到全局名称空间中
int main(){
    string name = "rouseon";
    //std::cout<<name;//当没有声明同名的局部变量时,存在二义性,编译器不允许
    std::cout<<name;//rouseon,而非shane,Shane::name被隐藏
    std::cout<<::name;//sheng,而非shane,全局名称空间内容的访问
    return 0;
}

限定的名称名称空间::名称内容

如:Shane::name Shane::get_other

关键字using

using声明using 限定的名称;

将限定的名称加入到using 限定的名称;所属的声明区域(可以是全局,也可以是代码块)中。

如:using Shane::name; using Shane::get_other;

using编译指令using namespace 名称空间;

将名称空间中所有的名称都加入到using namespace 名称空间;所属的声明区域(可以是全局,也可以是代码块)中。

如:using namespace Shane; using namespace Student::Shane;

注意

使用using声明和using编译指令会增加名称冲突的可能性;而仅仅在具体语句中使用限定的名称则不会产出冲突。

using声明和using编译指令的区别

  • using声明类似于声明了相应的名称,如果某个名称在代码块中已经声明了,则不能用using声明导入相同的名称。
  • using编译指令类似于将名称替换为限定的名称,如果某个名称在代码块中已经声明了,则实际上的限定的名称将被隐藏。

using编译指令的可传递性

namespace Student{
    int total_num;
    namespace Shane{
        int num;
        string name;
    }
}
namespace School{
    using namespace Student;
    int rooms;
}

传递性

using namespace School;
//等价于
using namespace School;
using namespace Student;

基于using namespace的可传递性,可给名称空间创建别名

//创建别名的名称空间,取将using namespace展开后的名称空间名
namespace SS = School::Shane;
//using声明
using SS::num;

未命名的名称空间

未命名的名称空间等价于静态全局变量

namespace
{
    int counts;
}
//等价于
static int counts;

一些建议

例程

#include <iostream>
#include <string>
using namespace std;

namespace shane{
    int num = 2;
    string name = "shane";
}
 
namespace student{
    int total_num = 2;
    //嵌套的名称空间
    namespace john{
        int num = 1;            //访问:student::num
        string name = "john";
    }
    //相当于声明了
    // int num = 1;
    // string name = "john";

    //名称空间中使用using编译指令或using声明
    using namespace shane;
    //等价于下面2行
    //using shane::num;
    //using shane::name;

    //num = 2;//错误,函数的外面只能写声明,不能写实现逻辑
}

namespace school{
    int rooms = 100;
    //名称空间中使用using编译指令或using声明
    using namespace student;
    //相当于声明了
    // int total_num = 2;        //访问:school::total_num
    // namespace john{
    //     int num = 1;            //访问:school::john::num
    //     string name = "john";    //访问:school::john::name
    // }
    // using namespace shane;    //访问:school::num
                                //访问:school::name
}
//错误的创建别名:"school::student"has not been declared
//namespace ssj = school::student::john;
//正确的创建别名:取将using namespace展开后的名称空间名
namespace sj = school::john;

using namespace school;
//等价于
//using namespace school;
//using namespace student;

string name = "sheng";//全局作用域中定义的名字被隐式地添加到全局名称空间中
int main(){
    string name = "rouseon";
    //cout<<name<<endl;//当没有声明同名的局部变量时,存在二义性,编译器不允许
    cout<<"name               "<<name<<endl;//rouseon,而非shane,Shane::name被隐藏
    cout<<"::name             "<<::name<<endl;//sheng,而非shane,全局名称空间内容的访问
    cout<<endl;
    cout<<"student::john::name"<<student::john::name<<endl;//john
    cout<<"student::john::num "<<student::john::num<<endl;//1
    cout<<"student::name      "<<student::name<<endl;//shane
    cout<<"student::num       "<<student::num<<endl;//2
    cout<<"student::total_num "<<student::total_num<<endl;//2
    cout<<endl;
    cout<<"school::rooms      "<<school::rooms<<endl;//100
    cout<<"school::john::name "<<school::john::name<<endl;//john
    cout<<"school::john::num  "<<school::john::num<<endl;//1
    cout<<"school::name       "<<school::name<<endl;//shane
    cout<<"school::num        "<<school::num<<endl;//2
    cout<<"school::total_num  "<<school::total_num<<endl;//2
    cout<<endl;
    cout<<"sj::name           "<<sj::name<<endl;//john
    cout<<"sj::num            "<<sj::num<<endl;//1
    return 0;
}

结果

name               rouseon
::name             sheng

student::john::namejohn
student::john::num 1
student::name      shane
student::num       2
student::total_num 2

school::rooms      100
school::john::name john
school::john::num  1
school::name       shane
school::num        2
school::total_num  2

sj::name           john
sj::num            1
Last modification:2021 年 04 月 27 日 10 : 42 : 32