• 命名空间


           所谓namespace,是指标识符的各种可见范围。C++标准程序库中的所有标识符都被定义于一个名为std的namespace中。

           <iostream>和<iostream.h>是不一样,前者没有后缀,实际上,在你的编译器include文件夹里面可以看到,二者是两个文件,打开文件就会发现,里面的代码是不一样的。后缀为.h的头文件c++标准已经明确提出不支持了,早些的实现将标准库功能定义在全局空间里,声明在带.h后缀的头文件里,c++标准为了和C区别开,也为了正确使用命名空间,规定头文件不使用后缀.h。因此,当使用<iostream.h>时,相当于在c中调用库函数,使用的是全局命名空间,也就是早期的c++实现;当使用<iostream>的时候,该头文件没有定义全局命名空间,必须使用namespaces td;这样才能正确使用cout。

           由于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"

    下面通过例程说明关键字namespace的用法。 

    #include  <iostream>  
    using namespace std;
    
    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;  
    
    }  

    运行结果:

    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
    202
    93

         从上面可以看出,名空间定义了一组变量和函数,它们具有相同的作用范围。对于不同的名空间,可以定义相同的变量名或函数名,在使用的时候,只要在变量名或函数名前区分开不同的名空间就可以了,
         名空间可以被嵌套定义,使用时要逐级对成员用名空间限定符::来引用。
    系统默认有一个全局名空间,它包含了所有的外部变量。这个命名空间没有名字,引用这个名空间里的变量时要使用名空间限定符::,前面没有名字。在不使用命名空间的情况下,我们知道,不可以在不同文件中定义相同名字的外部变量,这是因为它们属于同一个全局名空间,名字不可以重复。
          可以给名空间取一个别名。一般别名是一个比较短的名字,来简化编程。
          在原有定义好的名空间的基础上,随时可以往里增加成员。

         在前面的例程中可以看到,为了使用时的方便,又引入了关键字using。利用using声明可以在引用名空间成员时不必使用名空间限定符::。此外,关键字namespace和using的使用,对函数重载有一定的影响。 

    #include  <iostream>  
    using namespace std;
    
    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);  
    
    }  

    运行结果:  
    in  car  namespace:   
    in  car  namespace:  3.8  
    in  plane  namespace:  93  
    in  car  namespace:  93.75 

         说明:如果没有名空间的干扰,函数重载时选择规则将是非常简单。只要实参是double类型,则调用的是前面的函数;如果实参是int类型,则调用后面的函数。但是由于名空间的参与,就出现了上面的运行结果。所以在编程的时候一定要注意名空间对函数重载的影响。  

        最后,举一个例子,头文件h1.h里面包含命名空间ns,h1.cpp,h2.cpp,main.cpp三个编译单元分别包含该头文件,此时 h1.h里面包含命名空间ns的定义方式就要格外注意,否则引起重复定义错误。

    1、h1.h

    namespace ns
    {
        extern int i;
        void f(void);
    
        class A
        {
        public:
            A();
            int print(void);
        private:
            int m_data;
        };
    }

    2、h1.cpp版本一

    #include<iostream>
    #include "h1.h"
    using namespace std;
    using namespace ns;
    
    int ns::i = 10;
    
    void ns::f(void)
    {
        cout << "ns::f" << endl;
    }
    
    int ns::A::print(void)
    {
        cout << m_data << endl;
        return m_data;
    }
    
    
    ns::A::A()
    {
        m_data = 100;
    }

    2、h1.cpp版本二

    #include<iostream>
    #include "h1.h"
    using namespace std;
    namespace ns
    {
    
        int i = 10;
    
        void f(void)
        {
            cout << "ns::f" << endl;
        }
    
        int A::print(void)
        {
            cout << m_data << endl;
            return m_data;
        }
    
    
        A::A()
        {
            m_data = 100;
        }
    
    }

    3、h2.cpp

    #include<iostream>
    #include "h1.h"
    using namespace std;
    using namespace ns;
    
    void h(void)
    {
        i = 90;
        A a;
        a.print();
    
        cout << "h" << endl;
    }

    4、main.cpp

    #include<iostream>
    #include "h1.h"
    using namespace std;
    using namespace ns;
    
    int main(void)
    {
        i = 2;
        f();
    
        A a;
        a.print();
    
        return 0;
    }

    运行结果:

    ns::f
    100

  • 相关阅读:
    重新学习C#系列-02.静态类、静态字段和静态方法
    Appcan学习笔记(3)——tabview 静止页面左右滑动切换
    Appcan学习笔记(2)——子页面调用父页面的方法
    Appcan学习笔记(1)——父页面调用子页面的方法
    重新学习C#系列-01.方法参数
    WP8.1 Runtime应用利用HttpClient初始化数据的一些考虑
    C# socket通讯使用域名的方法
    RSA私钥加密
    RSA公钥加密
    13位时间戳转换成标准时间C#代码
  • 原文地址:https://www.cnblogs.com/zzj2/p/3053124.html
Copyright © 2020-2023  润新知