zoukankan      html  css  js  c++  java
  • C++ Namespace 详解

    命名空间的定义格式为:(取自C++标准文档)

    named-namespace-definition:       
                namespace identifier { namespace-body }
    unnamed-namespace-definition:       
                namespace { namespace-body }
    namespace-body:       
                declaration-seqopt
    有名的命名空间:       
    namespace 命名空间名 {              
                声明序列可选       
    }
     
    无名的命名空间:       
    namespace {              
                声明序列可选       
    }
     
     
    所谓C++中的namespace,是指标识符的各种可见范围。C++标准程序库中的所有标识符都被定义于一个名为std的namespace中。
    一、<iostream>和<iostream.h>
      <iostream>和<iostream.h>是不一样,前者没有后缀,实际上,在你的编译器include文件夹里面可以看到,二者是两个文件,打开文件就会发现,里面的代码是不一样的。
      后缀为.h的头文件c++标准已经明确提出不支持了,早些的实现将标准库功能定义在全局空间里,声明在带.h后缀的头文件里,c++标准为了 和C区别开,也为了正确使用命名空间,规定头文件不使用后缀.h。                            
      因此,当使用<iostream.h>时,相当于在c中调用库函数,使用的是全局命名空间,也就是早期的c++实现;当使 用<iostream>的时候,该头文件没有定义全局命名空间,必须使用namespace std;这样才能正确使用cout。 
    二、所谓namespace,是指标识符的各种可见范围。 
      C++标准程序库中的所有标识符都被定义于一个名为std的namespace中。 
      由于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; 
      因为标准库非常的庞大,所程序员在选择的类的名称或函数名时就很有可能和标准库中的某个名字相同。所以为了避免这种情况所造成的名字冲突,就 把标准库中的一切都被放在名字空间std中。但这又会带来了一个新问题。无数原有的C++代码都依赖于使用了多年的伪标准库中的功能,他们都是在全局空间 下的。 所以就有了<iostream.h>和<iostream>等等这样的头文件,一个是为了兼容以前的C++代码,一 个是为了支持新的标准。命名空间std封装的是标准程序库的名称,标准程序库为了和以前的头文件区别,一般不加".h" 。今天用了VISUAL C++写了个小程序(VS2005),很简单很简单的,但是就是编译不通过出现一个奇怪的问题:错误 1 error C2668: “max”: 对重载函数的调用不明确   

    最初代码如下:

    #include     
    using namespace std;   
    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;   
    }   
        我将这段代码放到VC++ 6.0下竟然通过了,程序运行也正常。这让我百思不得其解。后来终于弄明白了! 其实在std命名空间下还有一个MAX函数,而且实现的功能也是一样的……我昏。利用转到定义功能可以看到微软是怎么写MAX函数的。这里为了不被鄙视就不贴微软的代码了。明白了为什么出现这个错误我们就改写代码如下:
    #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++上都是用这种方式的,但是谭浩强的书上都是一句using namespace std;就搞定,我觉得蛮简洁的就一直用了,没想到带来那么多的问题,以前在友元函数上还碰到莫名的错误呢。   
      其实还有两个简单的解决方案,那就是把自己定义的函数改成其他的名字,或者直接用微软提供的函数。相信微软提供的效率绝对不会比我们写的低~好了,就写到这了。希望大家养成良好的编程习惯,^-^
     
      再者,由于大家一直都是直接使用以下微软自带的库文件:
    #include "iostream"
    using namespace std;

      此处链接为百度百科,对于命名空间的详解:http://baike.baidu.com/link?url=epiFYb_Hsw0nx6sig9eQefXTHPR1W2SuVnFazodsCueqt1g-ZCJXvkz8Pnx8zYSGrXFmSdTPQS1DYBTEMLYsgK

      其实,换句话自己理解,命名空间std比较特殊,因为std是微软已经定义好的标准库,假如你不使用“using namespace std”,则你就不能调用std库中的任何函数。看下面的代码:
    namespace test
    {
         template <class T>
         class allocator
         {
         public:
                   .........
         }
    }
      将一个声明的模板放在命名空间为test中,假如你在使用的时候没有使用“using namespace test”而去使用命名空间中声明的模板,这是就会出错,提示“error C3861: “class allocator”: 找不到标识符",其实可以这样理解,命名空间就是把空间内定义的内容装在一个盒子里,而命名空间名就是它的域,你只要调用了”using namespace 命名空间名“,相当于将域引入到了动作范围内,然后使用它就不会有错了。我自己写了一个很简单的测试例子:
    //Display.h  使用命名空间声明了一个显示函数
    #pragma once
    #include "iostream"
    using namespace std;
    
    namespace test
    {
         void Display()
        {
                cout<<"Hello World!!!"<<endl;
         }
    } 
    
    //Test.cpp 主函数调用命名空间内声明的函数
    #include "stdafx.h"
    #include "Display.h"
    using namespace test;//将此命名空间调用,将在下面可以直接使用命名空间中声明的显示函数
                         //假如将此句话屏蔽,编译提示错误"error C3861: “Display”: 找不到标识符"
    int _tmain(int argc, _TCHAR* argv[])
    {
          Display();
          return 0;
    } 
     
  • 相关阅读:
    MSSQLSERVER服务无法启动的解决方案
    引用类型和原始类型的对比(java)
    MVC中关于Membership类跟数据库的问题
    ASP.NET协作应用集成到trsids身份验证服务器的开发流程
    oracle的一知半解
    辨明你所从事的软件的类型
    sql数据库之间数据的转录
    设为首页 收藏(IE可用)
    如何缩减Try{}Catch{}Finally{}代码----定义一个公用的Try{}Catch{}Finally{}
    如何判断字符串是否存在数字
  • 原文地址:https://www.cnblogs.com/MrYuan/p/4955956.html
Copyright © 2011-2022 走看看