namespace ns1 //指定命名空间nsl
{
int a;
double b;
}
- namespace是定义命名空间所必须写的关键字,ns1是用户自己指定的命名空间的名字(可以用任意的合法标识符,这里用ns1是因为ns是namespace的缩写,含义清楚),在花括号内是声明块,在其中声明的实体称为命名空间成员(namespace member)。现在命名空间成员包括变量a和b,注意a和b仍然是全局变量,仅仅是把它们隐藏在指定的命名空间中而已。如果在程序中要使用变量a和b,必须加上命名空间名和作用域分辨符"::",如ns1::a,ns1::b。这种用法称为命名空间限定(qualified),这些名字(如ns1::a)称为被限定名(qualified name)。
- 命名空间的作用是建立一些互相分隔的作用域,把一些全局实体分隔开来。以免产生名字冲突
- 可以根据需要设置许多个命名空间,每个命名空间名代表一个不同的命名空间域,不同的命名空间不能同名。这样,可以把不同的库中的实体放到不同的命名空间中,或者说,用不同的命名空间把不同的实体隐蔽起来。过去我们用的全局变量可以理解为全局命名空间,独立于所有有名的命名空间之外,它是不需要用 namespace声明的,实际上是由系统隐式声明的,存在于每个程序之中。
- 在声明一个命名空间时,花括号内不仅可以包括变量,而且还可以包括以下类型:变量(可以带有初始化)、常量、函数(可以是定义或声明)、结构体、类、模板、命名空间(在一个命名空间中又定义一个命名空间,即嵌套的命名空间)。
如:
namespace ns1
{
const int RATE = 0.08; //常量
double pay; //变量
double tax() //函数
{
return a * RATE;
}
namespace ns2 //嵌套的命名空间
{
int age;
}
}
如果想输出命名空间nsl中成员的数据,可以采用下面的方法:
cout << ns1::RATE << endl;
cout << ns1::pay << endl;
cout << ns1::tax() << endl;
cout << ns1::ns2::age << endl; //需要指定外层的和内层的命名空间名
例:利用命名空间来解决名字冲突问题
//header1.h(头文件1)
#include
#include
using namespace std;
namespace ns1 //声明命名空间ns1
{
class Student //在命名空间ns1内声明Student类
{
public:
Student(int n, string nam, int a)
{ num = n; name = nam; age = a; }
void get_data();
private:
int num;
string name;
int age;
};
void Student::get_data() //定义成员函数
{
cout << num << " " << name << " " << age << endl;
}
double fun(double a, double b) //在命名空间ns1内定义fun函数
{ return sqrt(a + b); }
}
//header2.h(头文件2)
#include
#include
namespace ns2 //声明命名空间ns2
{
class Student //在命名空间ns2内声明Student类
{
public:
Student(int n, string nam, char s)
{ num = n; name = nam; sex = s; }
void get_data();
private:
int num;
string name;
char sex;
};
void Student::get_data() //定义成员函数
{ cout << num << " " << name << " " << sex << endl; }
double fun(double a, double b) //在命名空间ns2内定义fun函数
{ return sqrt(a - b); }
}
//main file(主函数)
#include
#include"header1.h" //包含头文件1
#include"header2.h" //包含头文件2
int main()
{
ns1::Student stud1(101, "Wang", 18); //用命名空间ns1中的Student类定义stud1
stud1.get_data(); //不要写成ns1::stud1.get_data()
cout << ns1::fun(5, 3) << endl; //调用命名空间ns1中的fun函数
ns2::Student stud2(102, "Li", 'f'); //用命名空间ns2中的Student类定义stud2
stud2.get_data();
cout << ns2::fun(5, 3) << endl; //调用命名空间ns1中的fun函数
return 0;
}
程序分析:
- 解决本题的关键是建立了两个命名空间ns1和ns2,将原来两个头件的内容分别放在命名空间ns1和ns2中。注意:在头文件中,不要把#include指令放在命名空间中,命名空间中的内容不能包括预处理指令,否则编译会出错。
- ns1::fun()和ns2::fun()是两个不同的函数。注意:对象stud1是用ns1::Student定义的,但对象stud1并不在命名空间ns1中。Stud1的作用域为main函数范围内。在调用对象stud1的成员函数get_data时,应写成stud1.get_data(),而不应写成ns1::stud1.get_data()。
命名空间名::命名空间成员名
。这种方法是有效的,能保证所引用的实体有唯一的名字。C++提供了一些机制,能简化使用命名空间中的成员的手续
namespace Television //声明命名空间,名为Television
{ … }
可以用一个较短而易记的别名代替它。如:namespace TV=Television; //别名TV与原名Television等价
也可以说,别名TV指向原名Television,在原来出现Television的位置都可以无条件地用TV来代替。
using ns1::Student;
Student studl(101, "Wang" ,18); //此处的Student相当于ns1::Student
//上面的语句相当于
nsl::Student studl(101, "Wang", 18);
//又如
using nsl::fun; //声明其后出现的fun是属于命名空间ns1中的fun
cout << fun(5, 3) << endl; //此处的fun函数相当于ns1::fun(5,3)
显然,这可以避免在每一次引用命名空间成员时都用命名空间限定,使得引用命名空间成员变得方便易用。
但是要注意:在同一作用域中用using声明的不同命名空间的成员中不能有同名的成员。
using namespace ns1;
,声明了在本作用域中要用到命名空间ns1中的成员,在使用该命名空间内的任何成员时都不必使用命名空间限定。如果在作了上面的声明后有以下语句:Student stud1(101, "Wang", 18); //Student隐含指命名空间ns1中的Student
cout << fun(5, 3) << endl; //这里的fun函数是命名空间ns1中的fun函数
namespace //命名空间没有名字
{
void fun() //定义命名空间成员
{ cout<<"OK."<<endl; }
}
由于没有名字,所以其它文件无法引用,它只在本文件的作用域内有效。无名命名空间的成员fun函数的作用域为文件A(确切地说,是从声明无名命名空间的位置开始到文件A结束)。在文件A中使用无名命名空间的成员,不必(也无法)用命名空间名限定。如果在文件A中有以下语句:fun();
,则执行无名命名空间中的成员fun函数,输出"OK."
std::cout<<"OK."<。在有的C++书中可以看到这样的用法。但是在每个cout,cm以及其他在std中定义的标识符前面都用命名空间std作为限定,显然是很不方便的。在大多数的C++书以及C++程序中常用using namespace语句对命名空间std进行声明,这样可以不必对每个命名空间成员一一进行处理,在文件的开头加入以下 using namespace声明:using namespace std;
using Std::string;
using Std::cout;
using Std::cin;
等。为了减少在每一个程序中都要重复书写以上的using声明,程序开发者往往把编写应用程序时经常会用到的命名空间std成员的using声明组成一个头文件,然后在程序中包含此头文件即可。
用C语言程序中使用的传统老方法。头文件名包括后缀.h,如stdio.h,math.h等。由于C语言没有命名空间,头文件并不存放在命名空间中,因此在C++程序文件中如果用到带后缀.h的头文件时,不必用命名空间。只需在文件中包含所用的头文件即可。如:#include
用C++的新方法。C++标准规定头文件不包括后缀.h,例如iostream、string。为了表示与C 语言的头文件有联系又有区别,C++所用的头文件名是在C语言的相应的头文件名(但不包括后缀.h)之前加一字母c。例如,C语言中有关输入与输出的头文件名为stdio.h在C++中相应的头文件名为cstdio。C语言中的头文件math.h,在C++中相应的头文什名为cmath。C语言中的头文件string.h在C++中相应的头文件名为cstring(注意在C++中,头文件cstring和头文件string不是同一个文件。前者提供C语言中对字符串处理的有关函数(如strcmp,ctrcpy)的声明,后者提供C++中对字符串处理的新功能。
#include
#include
using namespace std;
目前所用的大多数C++编译系统既保留了C的用法,又提供了C++的新方法。