C++命名空间

命名空间的存在就是为了给代码中的表示符提供一个范围,将代码组织到一个逻辑中,这样在不同命名空间中的同名函数也可以通过它所在的命名空间来区分开来了.我们经常使用的内容就是using namespace std,但是实际上在更多大型的工程组织中会用到更多稍微复杂些的命名空间的写法来保证冲突的避免.

namespace ContosoData
{
    class ObjectManager
    {
    public:
        void DoSomething() {}
    };
    void Func(ObjectManager) {}
}

Using指令

如果本地变量的名称与命名空间变量的名称相同,则隐藏命名空间变量。 使命名空间变量具有与全局变量相同的名称是错误的。

一般情况下,避免将 using 指令放置在头文件 (*.h) 中,因为任何包含该标头的文件都会将命名空间中的所有内容引入范围,这将导致非常难以调试的名称隐藏和名称冲突问题。 在头文件中,始终使用完全限定名。 如果这些名称太长,可以使用命名空间别名将其缩短。

声明命名空间和命名空间成员

指定的命名空间的成员可以在定义的名称的显式限定所声明的命名空间的外部进行定义。 但是,定义必须出现在命名空间中的声明位置之后,该命名空间包含在声明的命名空间中。 例如:

// defining_namespace_members.cpp
// C2039 expected
namespace V {
        void f();
    }

    void V::f() { }        // ok
    void V::g() { }        // C2039, g() is not yet a member of V

    namespace V {
        void g();
    }
}

并且当跨多个头文件声明命名空间成员,并且未以正确的顺序包含这些标头时,可能出现此错误。

嵌套命名空间

可以嵌套命名空间。 普通的嵌套命名空间具有对其父级成员的非限定访问权限,而父成员不具有对嵌套命名空间的非限定访问权限(除非它被声明为内联),如下面的示例所示:

namespace ContosoDataServer
{
    void Foo();

    namespace Details
    {
        int CountImpl;
        void Ban() { return Foo(); }
    }
    int Bar(){...};
    int Baz(int i) { return Details::CountImpl; }
}

普通嵌套命名空间可用于封装不属于父命名空间的公共接口的一部分的内部实现详细信息。

内联命名空间 (C++ 11)

与普通嵌套命名空间不同,内联命名空间的成员会被视为父命名空间的成员。

可以将内联命名空间用作版本控制机制,以管理对库的公共接口的更改。 例如,可以创建单个父命名空间,并将接口的每个版本封装到嵌套在父命名空间内的其自己的命名空间中。 保留最新或首选的版本的命名空间限定为内联,并因此以父命名空间的直接成员的形式公开。 调用 Parent::Class 的客户端代码将自动绑定到新代码。 通过使用指向包含该代码的嵌套命名空间的完全限定路径,选择使用较旧版本的客户端仍可以对其进行访问。

namespace Contoso
{
    namespace v_10
    {
        template <typename T>
        class Funcs
        {
        public:
            Funcs(void);
            T Add(T a, T b);
            T Subtract(T a, T b);
            T Multiply(T a, T b);
            T Divide(T a, T b);
        };
    }
    inline namespace v_20
    {
        template <typename T>
        class Funcs
        {
        public:
            Funcs(void);
            T Add(T a, T b);
            T Subtract(T a, T b);
            T Multiply(T a, T b);
            std::vector<double> Log(double);
            T Accumulate(std::vector<T> nums);
      };
    }
}

匿名或未命名的命名空间

可以创建显式命名空间,但不为其提供一个名称:

namespace
{
    int MyFunc(){}
}

这称为未命名的命名空间或匿名命名空间,在你想要使变量声明对于其他文件中的代码不可见(即 为它们提供内部链接),而不必创建已命名的命名空间时非常有用。 同一文件中的所有代码都可以看到未命名的命名空间中的标识符,但这些标识符以及命名空间本身在该文件外部(或更准确地说,在翻译单元外部)不可见。


layout: post

整理参考: https://msdn.microsoft.com/zh-cn/library/5cb46ksf.aspx




Enjoy Reading This Article?

Here are some more articles you might like to read next:

  • C++ 动态内存分配
  • 一个3D模型(译)
  • a distill-style blog post
  • 蒙特卡洛搜索树
  • Google Test 基础