C++ Namespace 详解

来源:互联网 发布:nat123端口映 编辑:程序博客网 时间:2024/06/06 02:06

所谓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  
0 0
原创粉丝点击