一、传统名称空间的重要概念
1--声明区域:可以在其中声明变量的区域。对于声明在函数外的变量,其声明空间为所在文件;对于声明在代码块内的变量,其名称空间为所在的代码块
2--潜在作用域:从声明点开始,到其声明空间的结尾
3--作用域:变量对程序可见的区域
作用域是潜在作用域的子集,潜在作用域是声明空间的子集。
#include <iostream>
using namespace std;
int main(void)
{
int a;
cout<<a<<endl;
if (1)
{
int a;
cout<<a<<endl;
}
}
第一个定义的a的声明空间是main函数,潜在作用域是从定义开始到main函数结束,但其作用域还要去掉if{}语句,因为在if语句中,第一个a被隐藏了。
之所以有上述的性质,是因为C++关于全局变量和局部变量的规则定义了一个名称空间层次。
二、全新名称空间特性
1--
C++定义了一种新的生命区域来创建命名的名称空间,这样子可以提供一个声明名称的区域,避免同名冲突。名称空间定义的语法如下:
namespace NAME
{
......
}
这就定义了一个名称为NAME的名称空间。
2--名称空间的元素包括变量、结构和函数
下面定义了一个名称为student的名称空间
namespace student
{
int age;
char name[40];
struct grade{int math;int English;};
void fetch();
}
3--名称空间可以是全局的,可以在别的名称空间中,但不能在代码块中
4--名称空间是开放的,可以用相同方式继续添加名称,比如我要给上述的名称空间student添加变量和函数定义,可以继续写:
namespace student
{
int classnum;
void fetch()
{
std::cout<<age<<std::endl;
}
}
(这里输入输出函数要不要加std::前缀呢?如果namespace代码块的前面已经使用using namespace std,则不用加std::前缀,因为using的作用域包括namespace定义;当然,也可以直接在namespace中直接使用using,但那样using的作用域就被限制在花括号中!不过,using反正可以重复使用,不像#include <iostream>只能用一次,所以这么多写一点不要紧!)
5--使用名称空间
当然是使用解析域作用符,略!
三、如何正确地using和::?
1--using声明
using std::cout;
将cout添加到using所属的声明区域中去
2--using编译指令
等效于有条件地把出现相应名称的变量、结构和函数名添加相应的前缀,下面两段程序等效:
#include <iostream>
using namespace std;
namespace student
{
int age=10;
}
int main(void)
{
using namespace student;
cout<<age<<endl;
int age=20;
cout<<age;
}
#include <iostream>
using namespace std;
namespace student
{
int age=10;
}
int main(void)
{
cout<<student::age<<endl;
int age=20;
cout<<age;
}
之所以说是有条件的,是因为函数块/代码块中定义的局部变量会覆盖student::age。
3--using声明和编译指令的差别!
先看下面这两段程序
#include <iostream>
using namespace std;
namespace student
{
int age=20;
}
int main(void)
{
using namespace student;
int age=10;
cout<<age;
}
#include <iostream>
using namespace std;
namespace student
{
int age=20;
}
int main(void)
{
using student::age;
int age=10;
cout<<age;
}
第一段age重复定义是合法的,但第二段是不合法的!这涉及到using和using namespace的区别。前者就好像在相应的代码块中声明了相应的名称一样,而后者保留了名称空间的层次独立性。
局部变量会覆盖名称空间变量,名称空间变量又会覆盖全局变量。
4--如何在using后使用全局变量?
已知名称空间变量会覆盖全局变量,对吧?但不管使用哪一种using,都可以用下面的方法来使用全局变量
在变量名前面加上::
#include <iostream>
using namespace std;
namespace student
{
int age=20;
}
int age=10;
int main(void)
{
using namespace student;
cout<<::age;
}
三、名称空间的其他性质
1--可以对名称空间进行嵌套
namespace student
{
int age;
char name[40];
namespace grade
{
int math;
int english;
}
}
使用时,如下操作即可:
student::grade::math
2--在名称空间中使用using声明
using namespace student_inf
{
using student::age;
}
这么做会使student_inf::age和student::age等效。为同一变量的不同名称
3--在名称空间中使用using namespace编译指令
using namespace student_inf
{
using namespace student;
int classnum;
}
这么做,可以让下面两个操作等价
using namespace student_inf
using namespace student_inf;
using namespace student;
编译指令具有传递性!
4--没有定义名称的名称空间等价于链接性为内部的静态变量!