C++命名空间

 

使用命名空间的目的是对标识符的名称进行本地化,以免命名冲突。在C++中,变量、函数和类都是大量存在的。若是没有命名空间,这些变量、函数、类的名称将都存在于全局命名空间中,会致使不少冲突。好比,若是咱们在本身的程序中定义了一个函数toupper(),这将重写标准库中的toupper()函 数,这是由于这两个函数都是位于全局命名空间中的。命名冲突还会发生在一个程序中使用两个或者更多的第三方库的状况中。此时,颇有可能,其中一个库中的名 称和另一个库中的名称是相同的,这样就冲突了。这种状况会常常发生在类的名称上。好比,咱们在本身的程序中定义了一个Stack类,而咱们程序中使用的某个库中也可能定义了一个同名的类,此时名称就冲突了。css

Namespace 关键字的出现就是针对这种问题的。因为这种机制对于声明于其中的名称都进行了本地化,就使得相同的名称能够在不一样的上下文中使用,而不会引发名称的冲突。或许命名空间最大的受益者就是C++中的标准库了。在命名空间出现以前,整个C++库都是定义在全局命名空间中的(这固然也是惟一的命名空间)。引入命名空间后,C++库就被定义到本身的名称空间中了,称之为std。这样就减小了名称冲突的可能性。咱们也能够在本身的程序中建立本身的命名空间,这样能够对咱们认为可能致使冲突的名称进行本地化。这点在咱们建立类或者是函数库的时候是特别重要的。ios

命名空间基础函数

namespace 关键字使得咱们能够经过建立做用范围来对全局命名空间进行分隔。本质上来说,一个命名空间就定义了一个范围。定义命名空间的基本形式以下:spa

namespace 名称{//声明}code

在命名空间中定义的任何东西都局限于该命名空间内。对象

下面就是一个命名空间的例子,其中对一个实现简单递减计数器的类进行了本地化。在该命名空间中定义了计数器类用来实现计数;其中的upperbound和lowerbound用来表示计数器的上界和下界。blog

演示命名空间it

namespace CounterNameSpace
{
    int upperbound;
    int lowerbound;
    class counter
    {
        int count;
   public:
     counter(int n)
     {
            if ( n <= upperbound ){
                count = n;
            } else  {
                count = upperbound;
            }
      }
    void reset(int n)
     {
       if ( n < upperbound )
            {
                count = n;
            }
        }
     int run() {
      if ( count > lowerbound)
       {
                return count--;
       } else {
                return lowerbound;
       }
      }
    };
}

 

其中的upperbound,lowerbound和类counter都是有命名空间CounterNameSpace定义范围的组成部分。io

在命名空间中声明的标识符是能够被直接引用的,不须要任何的命名空间的修饰符。例如,在CounterNameSapce命名空间中,run()函数中就能够直接在语句中引用lowerbound:class

if ( count > lowerbound)
{
return count--;
}

然而,既然命名空间定义了一个范围,那么咱们在命名空间以外就须要使用范围解析运算符来引用命名空间中的对象。例如,在命名空间CounterNameSpace定义的范围以外给upperbound赋值为10,就必须这样写:

CounterNameSpace::upperbound = 10;

或者在CounterNameSpace定义的范围以外想要声明一个counter类的对象就必须这样写:

CounterNameSpace::counter obj;

通常来说,在命名空间以外想要访问命名空间内部的成员须要在成员前面加上命名空间和范围解析运算符。

下面的程序演示了如何使用CounterNameSpace这个命名空间:

#include <iostream>
using namespace std;
namespace CounterNameSpace
{
    int upperbound;
    int lowerbound;
    class counter
    {
        int count;
    public:
        counter(int n)
        {
            if ( n <= upperbound )
            {
                count = n;
            } else
            {
                count = upperbound;
            }
        }
        void reset(int n)
        {
            if ( n < upperbound )
            {
                count = n;
            }
        }
        int run()
        {
          if ( count > lowerbound)
            {
                return count--;
            }
            else
                return lowerbound;
        }
    };
}
int main()
{
 CounterNameSpace::upperbound = 100;
 CounterNameSpace::lowerbound = 0;
 CounterNameSpace::counter ob1(10);
  int i;
  do {
   i = ob1.run();        
   cout << i << " ";
 } while (i > CounterNameSpace::lowerbound);
 cout << endl;
 CounterNameSpace::counter ob2(20);
do {
    i = ob2.run();
    cout << i << " ";
    } while (i > CounterNameSpace::lowerbound);
    cout << endl;
    ob2.reset(100);
    do
    {  i = ob2.run();
        cout << i << " ";
    } while (i > CounterNameSpace::lowerbound);
    cout << endl;
    return 0;
}

请注意:counter类以及upperbound和lowerbound的引用都是在前面加上了CounterNameSpace修饰符。可是,一旦声明了counter类型的对象,就没有必须在对该对象的任何成员使用这种修饰符了。所以ob1.run()是能够被直接调用的。其中的命名空间是能够被解析的。

相同的空间名称是能够被屡次声明的,这种声明向相互补充的。这就使得命名空间能够被分割到几个文件中甚至是同一个文件的不一样地方中。例如:

  1. namespace NS
    {
    int i;
    }
     
    //...
    namespace NS
    {
        int j;
    }

    其中命名空间NS被分割成两部分,可是两部分的内容倒是位于同一命名空间中的。也就是NS。最后一点:命名空间是能够嵌套的。也就是说能够在一个命名空间内部声明另外的命名空间。

using关键字

若是在程序中须要屡次引用某个命名空间的成员,那么按照以前的说法,咱们每次都要使用范围解析符来指定该命名空间,这是一件很麻烦的事情。为了解决这个问题,人们引入了using关键字。using语句一般有两种使用方式:

using namespace 命名空间名称;

using 命名空间名称::成员;

第一种形式中的命名空间名称就是咱们要访问的命名空间。该命名空间中的全部成员都会被引入到当前范围中。也就是说,他们都变成当前命名空间的一部分了,使用的时候再也不须要使用范围限定符了。第二种形式只是让指定的命名空间中的指定成员在当前范围中变为可见。咱们用前面的CounterNameSpace来举例,下面的using语句和赋值语句都是有效的:

using CounterNameSpace::lowerbound; //只有lowerbound当前是可见的

lowerbound = 10; //这样写是合法的,由于lowerbound成员当前是可见的

using CounterNameSpace; //全部CounterNameSpace空间的成员当前都是可见的

upperbound = 100; //这样写是合法的,由于全部的CounterNameSpace成员目前都是可见的

下面是咱们对以前的程序进行修改的结果:

使用using

#include <iostream>
 
using namespace std;
 
namespace CounterNameSpace
{
    int upperbound;
    int lowerbound;
    class counter
    {
        int count;
    public:
        counter(int n)
        {
            if ( n < upperbound)
            {
                count = n;
            }
            else
            {
                count = upperbound;
            }
        }
 
        void reset( int n )
        {
            if ( n <= upperbound )
            {
                count = n;
            }
        }
 
        int run()
        {
            if ( count > lowerbound )
            {
                return count--;
            }
            else
            {
                return lowerbound;
            }
        }
    }; 
}
int main()
{
    //这里只是用CounterNameSpace中的upperbound
    using CounterNameSpace::upperbound;
 
    //此时对upperbound的访问就不须要使用范围限定符了
    upperbound = 100;
    //可是使用lowerbound的时候,仍是须要使用范围限定符的
    CounterNameSpace::lowerbound = 0;
    CounterNameSpace::counter ob1(10);
    int i;
 
    do
    {
        i = ob1.run();
        cout << i << " ";
    }while( i > CounterNameSpace::lowerbound);
    cout << endl;
 
    //下面咱们将使用整个CounterNameSpace的命名空间
    using namespace CounterNameSpace;
    counter ob2(20);
    do
    {
        i = ob2.run();
        cout << i << " ";
    }while( i > CounterNameSpace::lowerbound);
    cout << endl;
 
    ob2.reset(100);
    lowerbound = 90;
    do
    {
        i = ob2.run();
        cout << i << " ";
    }while( i > lowerbound);
 
    return 0;
}
上面的程序还为咱们演示了重要的一点:当咱们用using引入一个命名空间的时候,若是以前有引用过别的命名空间(或者同一个命名空间),则不会覆盖掉对以前的引入,而是对以前引入内容的补充。也就是说,到最后,上述程序中的std和CounterNameSpace这两个命名空间都变成全局空间了。

有一种特殊的命名空间,叫作未命名的命名空间。这种没有名称的命名空间使得咱们能够建立在一个文件范围里可用的命名空间。其通常形式以下:
namespace
{
  //内容
}

std
命名空间

标准C++把本身的整个库定义在std命名空间中。这就是本书的大部分程序都有下面代码的缘由:

using namespace std;

这样写是为了把std命名空间的成员都引入到当前的命名空间中,以便咱们能够直接使用其中的函数和类,而不用每次都写上std::。

固然,咱们是能够显示地在每次使用其中成员的时候都指定std::,只要咱们喜欢。例如,咱们能够显示地采用以下语句指定cout:

std::cout << “显示使用std::来指定cout”;

若是咱们的程序中只是少许地使用了std命名空间中的成员,或者是引入std命名空间可能致使命名空间的冲突的话,咱们就没有必要使用using namespace std;了。然而,若是在程序中咱们要屡次使用std命名空间的成员,则采用using namespace std;的方式把std命名空间的成员都引入到当前命名空间中会显得方便不少,而不用每次都单独在使用的时候显示指定 转载地址:http://blog.renren.com/share/730973714/7874424429
相关文章
相关标签/搜索