命名空间 <iostream>和<iostream.h> 由程序设计者命名的内存区域

namespace_百度百科 https://baike.baidu.com/item/namespace/1700121?fromtitle=命名空间

namespace即“命名空间”,也称“名称空间” 、”名字空间”。VS.NET中的各种语言使用的一种代码组织的形式 通过名称空间来分类,区别不同的代码功能 同时也是VS.NET中所有类的完全名称的一部分。

命名空间是用来组织和重用代码的。如同名字一样的意思,NameSpace(名字空间),之所以出来这样一个东西,是因为人类可用的单词数太少,并且不同的人写的程序不可能所有的变量都没有重名现象,对于库来说,这个问题尤其严重,如果两个人写的库文件中出现同名的变量或函数(不可避免),使用起来就有问题了。为了解决这个问题,引入了名字空间这个概念,通过使用 namespace xxx;你所使用的库函数或变量就是在该名字空间中定义的,这样一来就不会引起不必要的冲突了。
通常来说,命名空间是唯一识别的一套名字,这样当对象来自不同的地方但是名字相同的时候就不会含糊不清了。使用扩展标记语言的时候,XML的命名空间是所有元素类别和属性的集合。元素类别和属性的名字是可以通过唯一XML命名空间来唯一。
在XML里,任何元素类别或者属性因此分为两部分名字,一个是命名空间里的名字另一个是它的本地名。在XML里,命名空间通常是一个统一资源识别符(URI)的名字。而URI只当名字用。主要目的是为了避免名字的冲突。
 

取名规则 

所谓namespace,是指标识符的各种可见范围。C++标准程序库中的所有标识符都被定义于一个名为std的namespace中。
一 :<iostream>和<iostream.h>格式不一样,前者没有后缀,实际上,在你的编译器include文件夹里面可以看到,二者是两个文件,打开文件就会发现,里面的代码是不一样的。后缀为.h的头文件c++标准已经明确提出不支持了,早些的实现将标准库功能定义在全局空间里,声明在带.h后缀的头文件里,c++标准为了和C区别开,也为了正确使用命名空间,规定头文件不使用后缀.h。 因此,当使用<iostream.h>时,相当于在c中调用库函数,使用的是全局命名空间,也就是早期的c++实现;当使用<iostream>的时候,该头文件没有定义全局命名空间,必须使用namespace std;这样才能正确使用cout。
二: 由于namespace的概念,使用C++标准程序库的任何标识符时,可以有三种选择:
1、直接指定标识符。例如std::ostream而不是ostream。完整语句如下: std::cout << std::hex << 3.4 << std::endl;
2、使用using关键字。 using std::cout; using std::endl; using std::cin; 以上程序可以写成 cout << std::hex << 3.4 << endl;
3、最方便的就是使用using namespace std; 例如: using namespace std;这样命名空间std内定义的所有标识符都有效(曝光)。就好像它们被声明为全局变量一样。那么以上语句可以如下写: cout <<hex << 3.4 << endl;因为标准库非常的庞大,所以程序员在选择的类的名称或函数名时就很有可能和标准库中的某个名字相同。所以为了避免这种情况所造成的名字冲突,就把标准库中的一切都被放在名字空间std中。但这又会带来了一个新问题。无数原有的C++代码都依赖于使用了多年的伪标准库中的功能,他们都是在全局空间下的。所以就有了<iostream.h>和<iostream>等等这样的头文件,一个是为了兼容以前的C++代码,一个是为了支持新的标准。命名空间std封装的是标准程序库的名称,标准程序库为了和以前的头文件区别,一般不加".h"。

C++命名空间 namespace的作用和使用解析 - 莫水千流 - 博客园 https://www.cnblogs.com/zhoug2020/p/5972439.html

C++命名空间 namespace的作用和使用解析

一、 为什么需要命名空间(问题提出)

命名空间是ANSIC++引入的可以由用户命名的作用域,用来处理程序中 常见的同名冲突。

在 C语言中定义了3个层次的作用域,即文件(编译单元)、函数和复合语句。C++又引入了类作用域,类是出现在文件内的。在不同的作用域中可以定义相同名字的变量,互不于扰,系统能够区别它们。

1、全局变量的作用域是整个程序,在同一作用域中不应有两个或多个同名的实体(enuty),包括变量、函数和类等。

例:如果在文件中定义了两个类,在这两个类中可以有同名的函数。在引用时,为了区别,应该加上类名作为限定: 
class A //声明A类 
{ public: 
void funl();//声明A类中的funl函数 
private: 
int i; }; 
void A::funl() //定义A类中的funl函数 
{…………}

class B //声明B类
{ public:
    void funl(); //B类中也有funl函数
    void fun2(); };
void B::funl() //定义B类中的funl函数
{ …………}

这样不会发生混淆。 
在 文件中可以定义全局变量(global variable),它的作用域是整个程序。如果在文件A中定义了一个变量a int a=3; 
在文件B中可以再定义一个变量a int a=5; 
在分别对文件A和文件B进行编译时不会有问题。但是,如果一个程序包括文件A和文件B,那么在进行连接时,会报告出错,因为在同一个程序中有两个同名的变量,认为是对变量的重复定义。 
可 以通过extern声明同一程序中的两个文件中的同名变量是同一个变量。如果在文件B中有以下声明: 
extem int a; 
表示文件B中的变量a是在其他文件中已定义的变量。由于有此声明,在程序编译和连接后,文件A的变量a的作用域扩展到了文件B。如果在文件B中不再对a赋值,则在文件B中用以下语句输出的是文件A中变量a的值: cout<

二、 什么是命名空间(解 决方案)

命名空间:实际上就是一个由程序设计者命名的内存区域,程序设计者可以根据需要指定一些有名字的空间域,把一些全局实体分别放在各个命名空间中,从而与其他全局实体分隔开来。 
如: namespace ns1 //指定命名中间nsl 
{ int a; 
double b; } 
namespace 是定义命名空间所必须写的关键字,nsl 是用户自己指定的命名空间的名字(可 以用任意的合法标识符,这里用ns1是因为ns是namespace的缩写,含义请楚),在花括号内是声明块,在其中声明的实体称为命名空间成员(namespace member)。现在命名空间成员包括变量a和b,注意a和b仍然是全局变量,仅仅是把它们隐藏在指定的命名空间中而已。如果在程序中要使用变量a和b,必须加上命名空间名和作用域分辨符“::”,如nsl::a,nsl::b。这种用法称为命名空间限定(qualified),这些名字(如nsl::a)称为被限定名 (qualified name)。C++中命名空间的作用类似于操作系统中的目录和文件的关系,由于文件很多,不便管理,而且容易重名,于是人们设立若干子目录,把文件分别放到不同的子目录中,不同子目录中的文件可以同名。调用文件时应指出文件路径。 
命名空间的作用:是建立一些互相分隔的作用域,把一些全局实体分隔开来。以免产生老点名叫李相国时,3个人都站起来应答,这就是名字冲突,因为他们无法辨别老师想叫的是哪一个李相国,同名者无法互相区分。为了避免同名混淆,学校把3个同名的学生分在3个班。这样,在小班点名叫李相国时,只会有一个人应答。也就是说,在该班的范围(即班作用域)内名字是惟一的。如果在全校集合时校长点名,需要在全校范围内找这个学生,就需要考虑作用域问题。如果校长叫李相国,全校学生中又会有3人一齐喊“到”,因为在同一作用域中存在3个同名学生。为了在全校范围内区分这3名学生,校长必须在名字前加上班号,如高三甲班的李相国,或高三乙班的李相国,即加上班名限定。这样就不致产生混淆。 
可以根据需要设置许多个命名空间,每个命名空间名代表一个不同的命名空间域,不同的命名空间不能同名。这样,可以把不同的库中的实体放到不同的命名空间中,或者说,用不同的命名空间把不同的实体隐蔽起来。过去我们用的全局变量可以理解为全局命名空间,独立于所有有名的命名空间之外,它是不需要用 namespace声明的,实际上是由系统隐式声明的,存在于每个程序之中。 
在声明一个命名空间时,花括号内不仅可以包括变量,而且还可以包括以下类型: 
·变量(可以带有初始化); 
·常量; 
·数(可以是定义或声明); 
·结构体; 
·类; 
·模板; 
·命名空间(在一个命名空间中又定义一个命名空间,即嵌套的命名空间)。 
例如 
namespace nsl 
{ const int RATE=0.08; //常量 
doublepay; //变量 
doubletax() //函数 
{return a*RATE;} 
namespacens2 //嵌套的命名空间 
{int age;} 

如果想输出命名空间nsl中成员的数据,可以采用下面的方法: 
cout<

三、 使用命名空间解决名字冲突(使用指南)

有了以上的基础后,就可以利用命名空间来解决名字冲突问题。现在,对例4程序进行修改,使之能正确运行。 
例5 利用命名空间来解决例4程序名字冲突问题。 
修改两个头文件,把在头文件中声明的类分别放在两个不同的命名空间中。 
//例8.5中的头文件1,文件名为header1.h 
using namespace std; 
#include 
#include 
namespace ns1 //声明命名空间ns1 
{ class Student //在命名空间nsl内声明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<

四、 使用命名空间成员的方法

从上面的介绍可以知道,在引用命名空间成员时,要用命名空间名和作用域分辨符对命名空间成员进行限定,以区别不同的命名空间中的同名标识符。即: 
命名空间名::命名空间成员名 
这种方法是有效的,能保证所引用的实体有惟一的名字。但是如果命名空间名字比较长,尤其在有命名空间嵌套的情况下,为引用一个实体,需要写很长的名字。在一个程序中可能要多次引用命名空间成员,就会感到很不方便。 
1 、使用命名空间别名 
可以为命名空间起一个别名(namespace alias),用来代替较长的命名空间名。如 
namespace Television //声明命名空间,名为Television 
{ … } 
可以用一个较短而易记的别名代替它。如: 
namespace TV=Television; //别名TV与原名Television等价 
也可以说,别名TV指向原名Television,在原来出现Television的位置都可以无条件地用TV来代替。 
2、使用using命名空间成员名 
using后面的命名空间成员名必须是由命名空间限定的名字。例如: 
using nsl::Student; 
以上语句声明:在本作用域(using语句所在的作用域)中会用到命名空间ns1中的成员Student,在本作用域中如果使用该命名空间成员时,不必再用命名空间限定。例如在用上面的using声明后,在其后程序中出现的Student就是隐含地指nsl::Student。 
using声明的有效范围是从using语句开始到using所在的作用域结束。如果在以上的using语句之后有以下语句: 
Student studl(101,”Wang”,18); //此处的Student相当于ns1::Student 
上面的语句相当于 
nsl::Student studl(101,”Wang”,18); 
又如 
using nsl::fun; //声明其后出现的fun是属于命名空间nsl中的fun 
cout<

五、 无名的命名空间

以上介绍的是有名字的命名空间,C++还允许使用没有名字的命名空间,如在文件A中声明了以下的无名命名空间: 
namespace //命名空间没有名字 
{ void fun( ) //定 义命名空间成员 
{ cout<<”OK.”<

六、标准命名空间std

为了解决C++标准库中的标识符与程序中的全局标识符之间以及不同库中的标识符之间的同名冲突,应该将不同库的标识符在不同的命名空间中定义(或声明)。标准C++库的所有的标识符都是在一个名为std的命名空间中定义的,或者说标准头文件(如iostream)中函数、类、对象和类模板是在命名空间 std中定义的。std是standard(标准)的缩写,表示这是存放标准库的有关内容的命名空间,含义请楚,不必死记。 
这样,在程序中用到C++标准库时,需要使用std作为限定。如 
std::cout<<”OK.”<

七、 使用早期的函数库

C语言程序中各种功能基本上都是由函数来实现的,在C语言的发展过程中建立了功能丰富的函数库,C++从C语言继承了这份宝贵的财富。在C++程序中可以使用C语言的函数库。 
如果要用函数库中的函数,就必须在程序文件中包含有关的头文件,在不同的头文件中,包含了不同的函数的声明。 
在C++中使用这些 头文件有两种方法。 
1、用C语言的传统方法 
头文件名包括后缀.h,如stdio.h,math.h等。由于C语言没有命名空间,头文件并不存放在命名空间中,因此在C++程序文件中如果用到带后缀.h的头文件时,不必用命名空间。只需在文件中包含所用的头文件即可。如 
#include 
2、用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++中,头文件cstnng和头文件strmg不是同一个文件。前者提供C语言中对字符串处理的有关函数(如strcmp,ctrcpy)的声明,后者提供C++中对字符串处理的新功能。 
此外,由于这些函数都是在命名空间std中声明的,因此在程序中要对命名空间std作声明。如: 
#include 
#include 
using namespace std; 
目前所用的大多数C++编译系统既保留了c的用法,又提供丁C++的新方法。下面两种用法等价,可以任选。 
C传 统方法 C++新方法 
#include #include 
#include #include 
#include #include 
using namespace std; 
可以使用传统的c方法,但应当提倡使用C++的新方法。

 
C++ 命名空间_w3cschool https://www.w3cschool.cn/cpp/cpp-namespaces.html

C++ 命名空间

2015-09-05

C++ 命名空间

假设这样一种情况,当一个班上有两个名叫 Zara 的学生时,为了明确区分它们,我们在使用名字之外,不得不使用一些额外的信息,比如他们的家庭住址,或者他们父母的名字等等。

同样的情况也出现在 C++ 应用程序中。例如,您可能会写一个名为 xyz() 的函数,在另一个可用的库中也存在一个相同的函数 xyz()。这样,编译器就无法判断您所使用的是哪一个 xyz() 函数。

因此,引入了命名空间这个概念,专门用于解决上面的问题,它可作为附加信息来区分不同库中相同名称的函数、类、变量等。使用了命名空间即定义了上下文。本质上,命名空间就是定义了一个范围。

定义命名空间

命名空间的定义使用关键字 namespace,后跟命名空间的名称,如下所示:

namespace namespace_name {
   // 代码声明
}

为了调用带有命名空间的函数或变量,需要在前面加上命名空间的名称,如下所示:

name::code;  // code 可以是变量或函数

让我们来看看命名空间如何为变量或函数等实体定义范围:

#include <iostream>
using namespace std;

// 第一个命名空间
namespace first_space{
   void func(){
      cout << "Inside first_space" << endl;
   }
}
// 第二个命名空间
namespace second_space{
   void func(){
      cout << "Inside second_space" << endl;
   }
}
int main ()
{
 
   // 调用第一个命名空间中的函数
   first_space::func();
   
   // 调用第二个命名空间中的函数
   second_space::func(); 

   return 0;
}

当上面的代码被编译和执行时,它会产生下列结果:

Inside first_space
Inside second_space

using 指令

您可以使用 using namespace 指令,这样在使用命名空间时就可以不用在前面加上命名空间的名称。这个指令会告诉编译器,后续的代码将使用指定的命名空间中的名称。

#include <iostream>
using namespace std;

// 第一个命名空间
namespace first_space{
   void func(){
      cout << "Inside first_space" << endl;
   }
}
// 第二个命名空间
namespace second_space{
   void func(){
      cout << "Inside second_space" << endl;
   }
}
using namespace first_space;
int main ()
{
 
   // 调用第一个命名空间中的函数
   func();
   
   return 0;
}

当上面的代码被编译和执行时,它会产生下列结果:

Inside first_space

using 指令也可以用来指定命名空间中的特定项目。例如,如果您只打算使用 std 命名空间中的 cout 部分,您可以使用如下的语句:

using std::cout;

随后的代码中,在使用 cout 时就可以不用加上命名空间名称作为前缀,但是 std 命名空间中的其他项目仍然需要加上命名空间名称作为前缀,如下所示:

#include <iostream>
using std::cout;

int main ()
{
 
   cout << "std::endl is used with std!" << std::endl;
   
   return 0;
}

当上面的代码被编译和执行时,它会产生下列结果:

std::endl is used with std!

using 指令引入的名称遵循正常的范围规则。名称从使用 using 指令开始是可见的,直到该范围结束。此时,在范围以外定义的同名实体是隐藏的。

不连续的命名空间

命名空间可以定义在几个不同的部分中,因此命名空间是由几个单独定义的部分组成的。一个命名空间的各个组成部分可以分散在多个文件中。

所以,如果命名空间中的某个组成部分需要请求定义在另一个文件中的名称,则仍然需要声明该名称。下面的命名空间定义可以是定义一个新的命名空间,也可以是为已有的命名空间增加新的元素:

namespace namespace_name {
   // 代码声明
}

嵌套的命名空间

命名空间可以嵌套,您可以在一个命名空间中定义另一个命名空间,如下所示:

namespace namespace_name1 {
   // 代码声明
   namespace namespace_name2 {
      // 代码声明
   }
}

您可以通过使用 :: 运算符来访问嵌套的命名空间中的成员:

// 访问 namespace_name2 中的成员
using namespace namespace_name1::namespace_name2;

// 访问 namespace:name1 中的成员
using namespace namespace_name1;

在上面的语句中,如果使用的是 namespace_name1,那么在该范围内 namespace_name2 中的元素也是可用的,如下所示:

#include <iostream>
using namespace std;

// 第一个命名空间
namespace first_space{
   void func(){
      cout << "Inside first_space" << endl;
   }
   // 第二个命名空间
   namespace second_space{
      void func(){
         cout << "Inside second_space" << endl;
      }
   }
}
using namespace first_space::second_space;
int main ()
{
 
   // 调用第二个命名空间中的函数
   func();
   
   return 0;
}

当上面的代码被编译和执行时,它会产生下列结果:

Inside second_space
 
 
 
 
 
原文地址:https://www.cnblogs.com/rsapaper/p/9826277.html