在C语言中,如果在已经包含了头文件
例如:
#include
#include
int printf=0;
int main()
{
return 0;
}
注意!如果把产生命名冲突的变量定义在函数内部,则编译器不会报错。因为头文件的展开是在全局域。如果定义在函数内部则是定义在了局部域,此时编译器会遵循“局部优先”原则。
这样的问题在大型的项目中尤为突出。一个大的项目会被分给很多个程序员去做,每个人各自写自己部分的代码都没有问题,但是当所有代码合在一起的时候,这样的命名冲突是难以避免的。为了解决这个问题,C++引入了——命名空间(namespace)的概念。
命名空间为什么能够解决“命名冲突”的问题呢?
事实上,命名空间定义了一个命名空间域(“域”是一个语法的概念)。而这个“域”,是在全局域里面的。命名空间解决“命名冲突”的原理是影响编译器查找其内容的规则 。
注意!命名空间不影响变量的存储位置和生命周期。命名空间里的变量仍然是全局变量,储存在静态存储区中。只是我们定义的“namespace”就像筑起一道隐形的围墙一样隔绝了编译器的查找,除非你通过特殊手段确定了你要找的东西在一个确定的命名空间里,才可以顺藤摸瓜找到它。(查找方法在后面会讲到。)
格式:
namespace king//namespace +命名空间的名字,此处名字为“king”
{
...//这里可以定义变量、函数以及类型。
}
提示:如果定义了结构体,后面引用的时候要注意域限定符的位置。后面会讲到。
注意!命名空间展开后的内容是在全局域里边的,因此不能在函数内定义。因为函数内部是一个局部作用域。
命名空间可以嵌套(即在一个namespace里面定义另一个)
namespace N
{
int a,b;
namespace N1
{
int a,b;
namespace N2
{
int a,b;
}
}
}
在不同的或者不同级的命名空间中使用一样变量名是不会冲突的。想象一下不同的院落,或者同一个院落里不同的房间,都是可以独立使用的。但是在使用的时候形式会有些区别。
C++的同一个project中是允许同时存在多个同名字的命名空间的。因为编译器最终会将他们合成到同一个命名空间里面。
注意!只有同级的同名命名空间会被合并成同一个命名空间。
namespace N1
{
namespace N1
{
}
}
这两个命名空间N1不会被合并。使用时也不一样。
命名空间内定义的变量、函数等是不可以直接被使用的。其使用有三种方法,以下小标题为使用格式。
说明: “::”——作用域限定符。表示作用域及其所属关系。
假设已经定义了一个名为“N”的命名空间。要引用N中的变量a。
int main()
{
printf("%d",N::a);
return 0;
}
using N::a;
int main()
{
printf("%d",a);
return 0;
}
注意!此格式使用于函数前面,只将N中的a展开,此后可以直接引用N中的a。但是如果还想使用N中的b,b仍然不能直接引用。
using namespace N;
int main()
{
printf("%d",a);
printf("%d",b);
return 0;
}
这种用法相当于将N中的全部内容都展开。类似于把围墙拆除,里面所有东西都暴露出来。之后引用N中的一切内容都可以直接引用。
注意!这种方法可以在日常练习中使用以图方便,但在正式的项目里不建议使用。因为这么做使C++的命名空间的引入失去了意义——它仍然无法解决命名冲突问题。
———————————————————————————————————————————
补充:如果是引用结构体,格式应该是 struct N::结构体名字 +变量名;例如,struct N::SLnode node;
如果是上文所提的嵌套定义,用第一种方法引用N2时应为——N::N1::N2::引用成员;
不同级的同名命名空间,以上文为例,低级的应为N1::N1::引用成员
命名空间的引入是为了解决C语言中命名冲突的问题。
命名空间的作用原理是影响编译器的查找规则,而不影响内容的生命周期和存储位置。命名空间里的内容存储在静态区。
命名空间只能在全局域定义。
命名空间可以嵌套定义。同级同名命名空间可以合并。