c++ namespace命名空间详解

What is a namespace?ios

A namespace defines an area of code in which all identifiers are guaranteed to be unique. By default, all variables and functions are defined in the global namespace. For example, take a look at the following snippet:app

1
2
3
4
5
int nX = 5;
int foo( int nX)
{
     return -nX;
}

Both nX and foo() are defined in the global namespace.ide

 

Namespaces allow to group entities like classes, objects and functions under a name. This way the global scope can be divided in "sub-scopes", each one with its own name.函数

命名空间把对象,函数,变量等分组,而后有一个名字。

The format of namespaces is:

namespace identifier
{
entities  
}

Where identifier is any valid identifier and entities is the set of classes, objects and functions that are included within the namespace. For example:this

实体能够是任何有效的标识符。spa

namespace myNamespace
{
  int a, b;
}

In this case, the variables a and b are normal variables declared within a namespace called myNamespace. In order to access these variables from outside the myNamespace namespace we have to use the scope operator ::. For example, to access the previous variables from outside myNamespace we can write:

code

1
2
myNamespace::a
myNamespace::b



The functionality of namespaces is especially useful in the case that there is a possibility that a global object or function uses the same identifier as another one, causing redefinition errors. For example:orm

// namespaces
#include <iostream>
using namespace std;

namespace first
{
  int var = 5;
}

namespace second
{
  double var = 3.1416;
}

int main () {
  cout << first::var << endl;
  cout << second::var << endl;
  return 0;
}

n this case, there are two global variables with the same name: var. One is defined within the namespace firstand the other one in second. No redefinition errors happen thanks to namespaces.

对象

using

The keyword using is used to introduce a name from a namespace into the current declarative region. For example:blog

#include <iostream>
using namespace std;

namespace first
{
  int x = 5;
  int y = 10;
}

namespace second
{
  double x = 3.1416;
  double y = 2.7183;
}

int main () {
  using first::x;
  using second::y;
  cout << x << endl;
  cout << y << endl;
  cout << first::y << endl;
  cout << second::x << endl;
  return 0;
}
5
2.7183
10
3.1416Notice how in this code, x (without any name qualifier) refers to first::x whereas y refers to second::y, exactly as our using declarations have specified. We still have access to first::y and second::x using their fully qualified names.

The keyword using can also be used as a directive to introduce an entire namespace:using能够引入整个namespace。
// using
#include <iostream>
using namespace std;

namespace first
{
  int x = 5;
  int y = 10;
}

namespace second
{
  double x = 3.1416;
  double y = 2.7183;
}

int main () {
  using namespace first;
  cout << x << endl;
  cout << y << endl;
  cout << second::x << endl;
  cout << second::y << endl;
  return 0;
}

In this case, since we have declared that we were using namespace first, all direct uses of x and y without name qualifiers were referring to their declarations in namespace first.

using and using namespace have validity only in the same block in which they are stated or in the entire code if they are used directly in the global scope. For example, if we had the intention to first use the objects of one namespace and then those of another one,

using 和using namespace 仅仅在他们声明的代码块有效,若是在全局做用域中直接使用,则在整个代码块中有效。

we could do something like:

// using namespace example
#include <iostream>
using namespace std;

namespace first
{
  int x = 5;
}

namespace second
{
  double x = 3.1416;
}

int main () {
  {
    using namespace first;
    cout << x << endl;
  }
  {2
    using namespace second;
    cout << x << endl;
  }
  return 0;
}
5
3.1416

Namespace alias


We can declare alternate names for existing namespaces according to the following format:

namespace new_name = current_name;
命名空间里的变量冲突:
#include<iostream>
using namespace std;
int x=1;
int y=2;
namespace first
{
    int var=5;
    int x=5;
    int y=10;
}
namespace second
{
    double var=3.1416;
    double x=5.5;
    double y=10.5;
}
int main()
{
     using namespace first;
     cout<<x<<endl; x显示冲突
}

命名空间嵌套:

C++ does not allow compound names for namespaces.

// pluslang_namespace.cpp
// compile with: /c
// OK
namespace a {
   namespace b {
      int i;
   }
}

// not allowed
namespace c::d {   // C2653
   int i;
}

下面的代码嵌套命名空间;

#include<iostream>
using namespace std;

namespace A
{
    void fun1(){ cout<<"fun1"<<endl; }

    namespace B
    {
        int a=1;
        void fun1(){ cout<<"b fun1"<<endl;}
    }
}
int main()
{
    using namespace A;
    fun1(); //print fun1
    B::fun1(); //print b fun1
}

咱们也能够用;

A::fun1();
A::B::fun1();

结果同样。(某个名字在本身的空间以外使用,在反复地在前面加上名字空间做为限定词)

 

无名名字空间,无名名字空间主要是保持代码的局部性,使用以下:

namespace
{
const int CVAR1 = 1;
void test();
}

因为该命名空间没有名字,不能被外部范围。(有什么用,咱们能够

但必定要注意的一点是,在C++编译器实现时,无名名字空间实际上是有名字的,这个隐含的名字跟它所在编译单元名字相关。因此基于这一点,咱们不能跨编译单元使用无名名字空间中的名字。

上面的声明等价于

namespace $$$
{
  const int CVAR1 = 1;
  void test();
}
using namespace $$$;

其中$$$在其所在的做用域里具备唯一性的名字,每一个编译单元里的无名名字空间也是互不相同的,using namesapce $$$只是当前的编译单元的隐含名字,因此不能跨编译单元使用无名名字空间中的名字。

假设上面的test方法在是a.h与a.cpp中定义与实现的,但在b.h或b.cpp中就不能直接使用test方法或CVAR1。由于在b的这个编译单元中连接的是b这个编译单元中的test符号,并不是a编译单元中的test符号,也就会出现未定符号。

 要避免名字空间使用很短的名字,也不能太长,更不能嵌套太深了,我的以为不要超过4层。

 

命名空间能够是不连续的

一个命名空间能够分散定义在多个文件中。不过,若是命名空间的一个部分须要使用一个定义在另外一文件中的名字,必须声明该名字

namespace namespace_name {
// declarations
}

若是namespace_name不是引用前面定义的命名空间,则用该名字建立新的命名空间,不然,这个定义打开一个已存在的命名空间,并将新声明加到那个命名空间。

接口和实现的分离

能够用分离的接口文件和实现文件构成命名空间。能够用与管理类和函数定义相同的方法来组织命名空间。定义多个不相关类型的命名空间应该使用分离的文件分别定义每一个类型。

// sales_item.h
namespace cplusplus_primer {
class SalesItem { /**/ };
SalesItem operator+(const SalesItem&amp;, const SalesItem&amp;);
}

// query.h
namespace cplusplus_primer {
class Query {
public:
    Query(const std::string&amp;);
    std::ostream &amp; display(std::ostream&amp;) const;
};
}

// sales_item.cpp
#include “sales_item.h”
namespace cplusplus_primer {
// definitions for SalesItem members and overloaded operators
}

// query.cpp
#include “query.h”
namespace cplusplus_primer {
// definitions for Query members and related functions
}

示例:

namespace C //命名空间不连续1.h
{
    class A
    {
    private:
        int a,b;
    public:
        void func();
    };
}
#include"命名空间不连续1.h"
#include<iostream>
using namespace std;
namespace C
{
    void A::func()
    {
        a=1,b=2;
        cout<<a<<b<<endl;
        cout<<"fun1"<<endl;
    }
}

int main()
{
    using namespace C;
    A a;
    a.func();
}

定义命名空间成员

能够在命名空间定义的外部定义命名空间成员,相似于在类外部定义类成员的方式。

// namespace members defined outside the namespace must use qualified names
cplusplus_primer::operator+(const SalesItem&amp;, const SalesItem&amp;)
{
    SalesItem ret(lhs);
    //
}