所谓C++中的namespace,是指标识符的各种可见范围。C++标准程序库中的所有标识符都被定义于一个名为std的namespace中。
有名的命名空间:
namespace 命名空间名 {
声明序列可选
}
无名的命名空间:
namespace {
声明序列可选
}
一、<iostream>和<iostream.h>
后缀为.h的头文件c++标准已经明确提出不支持了,早些的实现将标准库功能定义在全局空间里,声明在带.h后缀的头文件里,c++标准为了 和C区别开,也为了正确使用命名空间,规定头文件不使用后缀.h。
因此,当使用 <iostream.h>
时,相当于在c中调用库函数,使用的是全局命名空间,也就是早期的c++实现;当使用 <iostream>
的时候,该头文件没有定义全局命名空间,必须使用namespace std;这样才能正确使用cout。
<string.h>
是旧的C头文件,对应的是基于char*的字符串处理函数;<string>
是包装了std的C++头文件,对应的是新的strng类;<cstring>
是对应旧的C头文件的std版本。
二、使用命名空间
由于namespace的概念,使用C++标准程序库的任何标识符时,可以有三种选择:
+ 1、直接指定标识符。例如std::ostream而不是ostream。完整语句如下: std::cout << std::hex << 3.4 << std::endl;
+ 2、使用using关键字。 using std::cout; using std::endl; 以上程序可以写成 cout << std::hex << 3.4 << endl;
+ 3、最方便的就是使用using namespace std;
#include <iostream>
#include <sstream>
#include <string>
using namespace std;
//这样命名空间std内定义的所有标识符都有效。就好像它们被声明为全局变量一样。那么以上语句可以如下写:
cout<< hex << 3.4 <<endl;
无数原有的C++代码都依赖于使用了多年的伪标准库中的功能,他们都是在全局空间 下的。 所以就有了
#include
using std::cin;
using std::cout;
using std::endl;
template
T max (T a,T b)
{
return ((a>b)?a:b);
}
void main()
{
double x,y;
cin>>x>>y;
cout<<"Max number is "<<(max(x,y))<<endl;
cin>>x;
}
这是比较推荐的做法,因为C++ PRIMER, EFFECTIVE C++上都是用这种方式的。
测试例子
通过名空间,可以在同一个文件中使用相同的变量名或函数名,只要它们属于不同的名空间。另外,名空间可以使得代码操作具有相同名字但属于不同库的变量。而且,名空间也可以提高C语言与C++语言的兼容性。 下面通过例程说明关键字namespace的用法。
#include <conio.h>
#include <iostream.h>
namespace car // 名空间的定义
{
int model;
int length;
int width;
}
namespace plane
{
int model;
namespace size // 名空间的嵌套
{
int length;
int width;
}
}
namespace car // 添加名空间的成员
{
char * name;
}
namespace c=car; // 定义名空间的别名
int Time; // 外部变量属于全局名空间
void main()
{
car::length=3;
// 下面一句错误,故屏蔽掉
// width=2; // 对于非全局变量和当前有效临时变量应该指定名空间
plane::size::length=70;
cout<<"the length of plane is "<<plane::size::length<<"m."<<endl;
cout<<"the length of car is "<<car::length<<"m."<<endl;
// 使用名空间的别名
cout<<"the length of c is "<<c::length<<"m."<<endl;
int Time=1996; // 临时变量,应区别于全局变量
::Time=1997;
cout<<"Temp Time is "<<Time<<endl;
cout<<"Outer Time is "<<::Time<<endl;
// 使用关键字using
using namespace plane;
model=202;
size::length=93;
cout<<model<<endl;
cout<<size::length<<endl;
getch();
}
运行结果:
the length of plane is 70m.
the length of car is 3m.
the length of c is 3m.
Temp Time is 1996
Outer Time is 1997
说明:
- 从上面可以看出,名空间定义了一组变量和函数,它们具有相同的作用范围。对于不同的名空间,可以定义相同的变量名或函数名,在使用的时候,只要在变量名或函数名前区分开不同的名空间就可以了。
- 名空间可以被嵌套定义,使用时要逐级对成员用名空间限定符: :来引用。
- 系统默认有一个全局名空间,它包含了所有的外部变量。这个名空间没有名字,引用这个名空间里的变量时要使用名空间限定符: :,前面没有名字。在不使用名空间的情况下,我们知道,不可以在不同文件中定义相同名字的外部变量,这是因为它们属于同一个全局名空间,名字不可以重复。
- 可以给名空间取一个别名。一般别名是一个比较短的名字,来简化编程。
- 在原有定义好的名空间的基础上,随时可以往里增加成员。
如果没有名空间的干扰,函数重载时选择规则将是非常简单。只要实参是double类型,则调用的是前面的函数;如果实参是int类型,则调用后面的函数。但是由于名空间的参与,就出现了上面的运行结果。所以在编程的时候一定要注意名空间对函数重载的影响。
#include <conio.h>
#include <iostream.h>
namespace car // 名空间的定义
{
void ShowLength(double len) // 参数类型为d o u b l e
{
cout<<"in car namespace: "<<len<<endl;
}
}
namespace plane // 名空间的定义
{
void ShowLength(int len) // 参数类型为i n t
{
cout<<"in plane namespace: "<<len<<endl;
}
}
void main()
{
using namespace car;
ShowLength(3);
ShowLength(3.8);
using namespace plane;
ShowLength(93);
ShowLength(93.75);
getch();
}
运行结果:
in car namespace: 3
in car namespace: 3.8
in plane namespace: 93
in car namespace: 93.75