杜比尔炉石:名字空间

来源:百度文库 编辑:偶看新闻 时间:2024/04/27 08:34:32

对命名空间的理解

(2010-03-23 13:12:42)转载 标签:

杂谈

http://www.51xuewen.com/group/80/topic_1038.htm

http://wenda.tianya.cn/wenda/thread?tid=5881050611560ee4

http://zhidao.baidu.com/question/84156796.html?fr=qrl

很多初学C++的人,对于C++中的一些基本的但又不常用的概念感到模糊,命名空间(name space)就是这样一个概念 C++中采用的是单一的全局变量命名空间。在这单一的空间中,如果有两个变量或函数的名字完全相同,就会出现冲突。当然,你也可以使用不同的名字,但有时我们并不知道另一个变量也使用完全相同的名字;有时为了程序的方便,必需使用同一名字。比如你定义了一个变量 string user_name, 有可能在你调用的某个库文件或另外的程序代码中也定义了相同名字的变量,这就会出现冲突。命名空间就是为解决C++中的变量、函数的命名冲突而服务的。解决的办法就是将你的strTemp变量定义在一个不同名字的命名空间中。就好像张家有电视机,李家也有同样型号的电视机,但我们能区分清楚,就是因为他们分属不同的家庭。例如:

#include     
#include     
using namespace std;    
//using namespace编译指示,使在C++标准类库中定义的名字在本程序中可以使用    
//否则,iostream,string 等c++标准类就不可见了,编译就会出错。    
//两个在不同命名空间中定义的名字相同的变量    
namespace myown1{    
        string user_name = "myown1";    
       
namespace myown2{    
        string user_name = "myown2";    
       
int main()    
   
     cout<< " "    
        << "Hello, "    
        << myown1::user_name    //用命名空间限制符myown1访问变量user_name    
        << "... and goodbye! ";    
     cout<< " "    
        << "Hello, "    
        << myown2::user_name //用命名空间限制符myown2访问变量user_name    
        << "... and goodbye! ";    
    return 0;    
  


          当然,我们也可以使用程序开头的预编译指示来使用命名空间中的名字。使用预编译指示的好处在于在程序中不必显式地使用命名空间限制符来访问变量。以上主程序可修改为:

#include    
#include    
using namespace std;

namespace myown1{   
        string user_name = "myown1";   
      
namespace myown2{   
        string user_name = "myown2"; 
}
int main()   
  
    using namespace myown1;   
     cout<< " "   
        << "Hello, "   
        << user_name   
        << "... and goodbye! ";   
//   using namespace myown2;   
     cout<< " "   
        << "Hello, "   
        << myown2::user_name //用命名空间限制符myown2访问变量user_name   
        << "... and goodbye! ";   
    return 0; 
}

        但第二个变量必需用命名空间限制符来访问,因为此时myown1空间中的变量已经可见,如果不加限制,编译器就会无法识别是那一个命名空间中的变量。这一点一定要注意。

以上只是初学者不清楚的一个概念,在以后的文章中还将继续讨论其它的一些概念。

 

 

######################################
有些书说有些头文件不在std里是什么意思?
######################################
那些书那样说会造成困惑,因为名字空间,就像函数、
结构、类等等,是用代码来表达的一种语言机制。

std(standard的缩写)是标准C++里必须存在的一个
名字空间的名字。所有实现标准C++的编译器都
必须确保这空间的存在。

名字空间声明是这样表达的:
namespace x {
   // 创建新名字
}

x是该名字空间的名字。

头文件装代码,代码表达名字空间。
所以应该说“有些头文件的内容不在std里”。
具体的意思就是,在那些头文件里,
没有任何代码是在“namespace std { }”的括号里的。


######################################
std里包含些什么?
######################################
std里包含标准C++库里的所有名字(类名、
函数名、...)。


######################################
为什么不用std就不能使用cout?
######################################
不是不能使用,只是不能直接写cout,必需用空间名和
名字空间限制符作为前缀,写成std::cout。

用某个名字做名字空间声明的时候,若已有同名的
名字空间存在,就是仅仅把括号里的名字加进去,
否则先创建空间,后加入括号里的名字。

加入名字空间后的名字都是对全局空间隐藏的,
但该名字空间的名字却不隐藏(除非该空间在另一个
名字空间里)。
cout隐藏在std里,但std本身不隐藏,所以
你“#include”了之后,不必做
使用声明便可直接用std,通过它访问cout。

若你做了使用声明,对该使用声明所处的作用域的隐藏便
被抵消(作用域的开端到声明之间的那段除外),
即不必使用空间名和名字空间限制符作为前缀。

######################################
头文件中声明的东西为什么在使用的时候需要
先using namespace std;一下?
######################################
你已经知道做使用声明是要讨个方便而不是一种必要。

我们作个总结性的复习吧。

(A)这简单的程序里只有全局和局部空间,没有其它的名字空间:

void  main( ) {
   std::cout << "";  // 错误:std不存在。
   cout << "";       // 错误:std不存在cout就不用提了。
}


(B)这个则多了一个叫std的名字空间。std这名字也可见了:

#include
void main( ) {
   std::cout << "";  // OK:可通过std骚扰cout。
   cout << "";       // 错误:cout仍然被包在std里面,不可见。
}

iostream头文件里有std的声明。在编译之前,
预处理器会用iostream里的全部内容来代替
“#include”这个预处理器指示符。
效果是,这程序包含iostream里的所有代码。
include是包含的意思。

包含指示是在全局空间里,所以在指示之后的任何地方,
std这个名字是可见、可访问的。


(C)这个不包含声明std的代码却尝试打开std包,
    落了个跟(A)一样狼狈的下场:

using namespace std;
void  main( ) {
   std::cout << "";  // 错误:std不存在。
   cout << "";       // 错误:std不存在cout就不用提了。
}

(D)这个声明了std(曝露了std)并把std打开,
    让里面的名字(cin、cout、cerr、...)跟
    std一样暴露。

 

 

C++为了兼容C,所以头文件按照C的风格写也编译得过
例如
#include
#include
之类的
这里是把头文件的文件名写全了的,所以直接可以通过

而C++里面则使用了命名空间,即namespace,
而且把所有的库全部放在一个叫做std的标准命名空间中
使用这个命名空间就需要加using namespace std
而在头文件include的时候就可以直接写这个命名空间中的简写
例如
#include
#include
using namespace std;  C++自带的命名空间除了std以外还有什么?看情况。
1.如果你使用了外部库的话那么可能有其它命名空间
2.如果你使用的是VC7.1以上的版本的VC比如VC2005、2008,那么你会拥有stdext命名空间,这些空间下面有hash_set和hash_map可以用。
比如:
#include
using namespace stdext;