使用命名空间解决名字冲突 <?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

现在,对例1程序进行修改,使之能正确运行。例2利用命名空间来解决例1程序名字冲突问题。修改两个头文件,把在头文件中声明的类分别放在两个不同的命名空间中。
//header1.h  (头文件1)
#include <string>
#include <cmath>
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 <string>
#include <cmath>

using namespace std;
namespace ns2                      //声明命名空间ns2
 {class Student
{public:
Student(int n,string nam,char s)
{num=n;name=nam;sex=s;}
void get_data( );
private:
int num;
char name[20];
char sex;
};
void Student::get_data( )
   {cout<<num<< <<name<< <<sex<<endl;
}
double fun(double a,double b)
{return sqrt(a-b);}
 }
//main file (主文件)
#include <iostream>
#include cc14-5-h1.h          //包含头文件1
#include cc14-5-h2.h          //包含头文件2
using namespace std;
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;
 }
程序能顺利通过编译,并得到以下运行结果:
101 Wang 18(对象stud1中的数据)
2.82843               (5+3的开方值)
102 Li f              (对象stud2中的数据)
1.41421               (5-3的开方值)

 

 

使用命名空间成员的方法

在引用命名空间成员时,要用命名空间名和作用域分辨符对命名空间成员进行限定,以区别不同的命名空间中的同名标识符。即
命名空间名::命名空间成员名
这种方法是有效的,能保证所引用的实体有惟一的名字。但是如果命名空间名字比较长,尤其在有命名空间嵌套的情况下,为引用一个实体,需要写很长的名字。在一个程序中可能要多次引用命名空间成员,就会感到很不方便。为此,C++提供了一些机制,能简化使用命名空间成员的手续。
1 使用命名空间别名
可以为命名空间起一个别名(namespace alias),用来代替较长的命名空间名。如
namespace Television//声明命名空间,名为Television
 {…}
可以用一个较短而易记的别名代替它。如
namespace TV = Television;//别名TV与原名Television等价
2 使用using 命名空间成员名
using后面的命名空间成员名必须是由命名空间限定的名字。例如
using ns1::Student;
using声明的有效范围是从using语句开始到using所在的作用域结束。如果在以上的using语句之后有以下语句
Student stud1(101,Wang,18);//此处的Student相当于ns1::Student
上面的语句相当于
ns1::Student stud1(101,Wang,18);
又如
using ns1::fun;//声明其后出现的fun是属于命名空间ns1中的fun
cout<<fun(5,3)<<endl;        //此处的fun函数相当于ns1::fun(5,3)
显然,这可以避免在每一次引用命名空间成员时都用命名空间限定,使得引用命名空间成员方便易用。
但是要注意: 在同一作用域中用using声明的不同命名空间的成员中不能有同名的成员。例如
using ns1::Student;//声明其后出现的Student是命名空间ns1中的Student
using ns2::Student;        //声明其后出现的Student是命名空间ns2中的Student
Student stud1;             //请问此处的Student是哪个命名空间中的Student?
产生了二义性,编译出错。
3 使用using namespace 命名空间名
能否在程序中用一个语句就能一次声明一个命名空间中的全部成员呢?C++提供了using namespace语句来实现这一目的。using namespace语句的一般格式为
using namespace命名空间名;
例如
using namespace ns1;
声明了在本作用域中要用到命名空间ns1中的成员,在使用该命名空间的任何成员时都不必用命名空间限定。如果在作了上面的声明后有以下语句:
Student stud1(101,Wang,18);//Student隐含指命名空间ns1中的Student
cout<<fun(5,3)<<endl;          //这里的fun函数是命名空间ns1中的fun函数
在用using namespace声明的作用域中,命名空间ns1的成员就好像在全局域声明的一样。因此可以不必用命名空间限定。显然这样的处理对写程序比较方便。但是如果同时用using namespace声明多个命名空间时,往往容易出错。因此只有在使用命名空间数量很少,以及确保这些命名空间中没有同名成员时才用using namespace语句。

 

无名的命名空间

以上介绍的是有名字的命名空间,C++还允许使用没有名字的命名空间,如在文件A中声明了以下的无名命名空间:
namespace//命名空间没有名字
{void fun()                          //定义命名空间成员
    {cout<<OK.<<endl;}
}
由于命名空间没有名字,在其他文件中显然无法引用,它只在本文件的作用域内有效。无名命名空间的成员fun函数的作用域为文件A。在文件A中使用无名命名空间的成员,不必(也无法)用命名空间名限定。如果在文件A中有以下语句:
fun();
则执行无名命名空间中的成员fun函数,输出″OK.
在本程序中的其他文件中也无法使用该fun函数,也就是把fun函数的作用域限制在本文件范围中。

 

 

标准命名空间 std

为了解决C++标准库中的标识符与程序中的全局标识符之间以及不同库中的标识符之间的同名冲突,应该将不同库的标识符在不同的命名空间中定义(或声明)。标准C++库的所有的标识符都是在一个名为std的命名空间中定义的,或者说标准头文件(iostream)中函数、类、对象和类模板是在命名空间std中定义的。这样,在程序中用到C++标准库时,需要使用std作为限定。如
std::cout<<OK.<<endl; //声明cout是在命名空间std中定义的流对象
在大多数的C++程序中常用using namespace语句对命名空间std进行声明,这样可以不必对每个命名空间成员一一进行处理,在文件的开头加入以下using namespace声明
using namespace std;
这样,在std中定义和声明的所有标识符在本文件中都可以作为全局量来使用。但是应当绝对保证在程序中不出现与命名空间std的成员同名的标识符。由于在命名空间std中定义的实体实在太多,有时程序设计人员也弄不清哪些标识符已在命名空间std中定义过,为减少出错机会,有的专业人员喜欢用若干个“using 命名空间成员声明来代替“using namespace 命名空间声明,如
using std::string;
using std::cout;
using std::cin;
等。为了减少在每一个程序中都要重复书写以上的using声明,程序开发者往往把编写应用程序时经常会用到的命名空间std成员的using声明组成一个头文件,然后在程序中包含此头文件即可。