• linkedu视频
  • 平面设计
  • 电脑入门
  • 操作系统
  • 办公应用
  • 电脑硬件
  • 动画设计
  • 3D设计
  • 网页设计
  • CAD设计
  • 影音处理
  • 数据库
  • 程序设计
  • 认证考试
  • 信息管理
  • 信息安全
菜单
linkedu.com
  • 网页制作
  • 数据库
  • 程序设计
  • 操作系统
  • CMS教程
  • 游戏攻略
  • 脚本语言
  • 平面设计
  • 软件教程
  • 网络安全
  • 电脑知识
  • 服务器
  • 视频教程
  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号
您的位置:首页 > 程序设计 >C语言 > C++编程中的命名空间基本知识讲解

C++编程中的命名空间基本知识讲解

作者: 字体:[增加 减小] 来源:互联网 时间:2017-05-28

通过本文主要向大家介绍了c++编程,c++编程软件,c++编程软件下载,c++编程思想,c++游戏编程等相关知识,希望对您有所帮助,也希望大家支持linkedu.com www.linkedu.com

命名空间是一个声明性区域,为其内部的标识符(类型、函数和变量等的名称)提供一个范围。命名空间用于将代码组织到逻辑组中,还可用于避免名称冲突,尤其是在基本代码包括多个库时。命名空间范围内的所有标识符彼此可见,而没有任何限制。命名空间之外的标识符可通过使用每个标识符的完全限定名(例如 std::vector<std::string> vec;)来访问成员,也可通过单个标识符的 using 声明 (using std::string) 或命名空间中所有标识符的 using 指令 (C++) (using namespace std;) 来访问成员。头文件中的代码应始终使用完全限定的命名空间名称。
下面的示例演示了一个命名空间声明和命名空间之外的代码可访问其成员的三种方法。

namespace ContosoData
{ 
 class ObjectManager 
 {
 public:
  void DoSomething() {}
 };
 void Func(ObjectManager) {}
}
</div>

使用完全限定名:

ContosoData::ObjectManager mgr;
mgr.DoSomething();
ContosoData::Func(mgr);
</div>

使用 using 声明,以将一个标识符引入范围:

using WidgetsUnlimited::ObjectManager;
ObjectManager mgr;
mgr.DoSomething();
</div>

使用 using 指令,以将命名空间中的所有内容引入范围:

using namespace WidgetsUnlimited;
ObjectManager mgr;
mgr.DoSomething();
Func(mgr);
</div>

using 指令
通过 using 指令,可使用命名空间中的所有名称,而不需要命名空间名称为显式限定符。如果在一个命名空间中使用多个不同的标识符,则在实现文件中使用 using 指令(即*.cpp);如果仅使用一个或两个标识符,则考虑使用声明,以仅将这些标识符而不是命名空间中的所有标识符引入范围。如果本地变量的名称与命名空间变量的名称相同,则隐藏命名空间变量。使命名空间变量具有与全局变量相同的名称是错误的。
注意
using 指令可以放置在 .cpp 文件的顶部(在文件范围内),或放置在类或函数定义内。
一般情况下,避免将 using 指令放置在头文件 (*.h) 中,因为任何包含该标头的文件都会将命名空间中的所有内容引入范围,这将导致非常难以调试的名称隐藏和名称冲突问题。在头文件中,始终使用完全限定名。如果这些名称太长,可以使用命名空间别名将其缩短。(请参阅下文。)
声明命名空间和命名空间成员
通常情况下,在头文件中声明一个命名空间。如果函数实现位于一个单独的文件中,则限定函数名称,如本示例所示。

//contosoData.h 
#pragma once
namespace ContosoDataServer
{
 void Foo();
 int Bar();

}
contosodata.cpp 中的函数实现应使用完全限定名,即使将一个 using 指令放置于文件的顶部也是如此:
#include "contosodata.h"
using namespace ContosoDataServer; 

void ContosoDataServer::Foo()
{
 //no qualification because using directive above
 Bar(); 
}

int ContosoDataServer::Bar(){return 0;}

</div>

可以在单个文件中的多个块中声明命名空间,也可在多个文件中声明命名空间。编译器在预处理过程中将各部分联接在一起,产生的命名空间中包含所有部分中声明的所有成员。一个相关示例是在标准库中的每个头文件中声明的 std 命名空间。
指定的命名空间的成员可以在定义的名称的显式限定所声明的命名空间的外部进行定义。但是,定义必须出现在命名空间中的声明位置之后,该命名空间包含在声明的命名空间中。例如:

// 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();
 }
}

</div>

当跨多个头文件声明命名空间成员,并且未以正确的顺序包含这些标头时,可能出现此错误。
全局命名空间
如果未在显式命名空间中声明某个标识符,则该标识符属于隐式全局命名空间的一部分。通常情况下,如果可能,尝试避免在全局范围内进行声明,入口点 main 函数除外,它必须位于全局命名空间中。若要显式限定全局标识符,请使用没有名称的范围解析运算符,如 ::SomeFunction(x); 中所示。这将使标识符与任何其他命名空间中具有相同名称的任何内容区分开来,并且还有助于使其他人更轻松地了解你的代码。
Std 命名空间
所有 C++ 标准库类型和函数都在 std 命名空间或嵌套在 std 内的命名空间中进行声明。
嵌套命名空间
可以嵌套命名空间。普通的嵌套命名空间具有对其父级成员的非限定访问权限,而父成员不具有对嵌套命名空间的非限定访问权限(除非它被声明为内联),如下面的示例所示:

namespace ContosoDataServer
{
 void Foo(); 

 namespace Details
 {
  int CountImpl;
  void Ban() { return Foo(); }
 }

 int Bar(){...};
 int Baz(int i) { return Details::CountImpl; } 

}

</div>

普通嵌套命名空间可用于封装不属于父命名空间的公共接口的一部分的内部实现详细信息。
内联命名空间 (C++ 11)
与普通嵌套命名空间不同,内联命名空间的成员会被视为父命名空间的成员。这一特性使针对重载函数的依赖于参数的查找可以对父命名空间和嵌套内联命名空间中具有重载的函数起作用。它还可让你在内联命名空间中声明的模板的父命名空间中声明专用化。下面的示例演示在默认情况下,外部代码如何绑定到内联命名空间:

//Header.h
#include <string>


namespace Test
{
 namespace old_ns
 {
  std::string Func() { return std::string("Hello from old"); }
 }

 inline namespace new_ns
 {
  std::string Func() { return std::string("Hello from new"); }
 }
}

#include "header.h"
#include <string>
#include <iostream>

int main()
{
 using namespace Test;
 using namespace std;

 string s = Func();
 std::cout << s << std::endl; // "Hello from new"
 return 0;
}

</div>

下面的示例演示如何在内联命名空间中声明的模板的父命名空间中声明专用化:

namespace Parent
{
 inline namespace new_ns
 {
   template <typename T>
   struct C
   {
    T member;
   };
 }
  template<>
  class C<int> {};
}
</div>

 

可以将内联命名空间用作版本控制机制,以管理对库的公共接口的更改。例如,可以创建单个父命名空间,并将接口的每个版本封装到嵌套在父命名空间内的其自己的命名空间中。保留最新或首选的版本的命名空间限定为内联,并因此以父命名空间的直接成员的形式公开。调用 Parent::Class 的客户端代码将自动绑定到新代码。通过使用指向包含该代码的嵌套命名空间的完全限定路径,选择使用较旧版本的客户端仍可以对其进行访问。
Inline 关键字必须应用到编译单元中命名空间的第一个声明中。
下面的示例演示一个接口的两个版本,每个版本位于一个嵌套命名空间中。通过 v_10 接口对 v_20 命名空间进行了某些修改,且该命名空间被标记为内联。使用新库并调用 Contoso::Funcs::Add 的客户端代码将调用 v_20 版本。尝试调用 Contoso::Funcs::Divide 的代码现在将获取一个编译时错误。如果它们确实需要该函数,则仍可以通过显式调用 Contoso::v_10::Funcs::Divide 访问 v_10 版本。

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);
  };
 }
}

</div>


命名空间别名
命名空间名称必须是唯一的,这意味着通常它们不应太短。如果名称的长度使代码难以阅读,或在不能使用 using 指令的头文件中进行键入单调乏味,则可以使用用作实际名称的缩写的命名空间别名。例如:

namespace a_very_long_namespace_name { class Foo {}; }
namespace AVLNN = a_very_long_namespace_name;
void Bar(AVLNN::Foo foo){ }
</div>

分享到:QQ空间新浪微博腾讯微博微信百度贴吧QQ好友复制网址打印

您可能想查找下面的文章:

  • C++的虚析构详解及实例代码
  • C++二分查找(折半查找)算法实例详解
  • C++ 中函数重载、覆盖与隐藏详解
  • 学习C++编程的必备软件
  • C++调用Python基础功能实例详解
  • C++中函数重载实例详解
  • C++模版函数详解
  • 详解C++11中的右值引用与移动语义
  • C++详解默认参数的构造函数及简单实例代码
  • C++如何动态的生成对象详解

相关文章

  • 2017-05-28详解C语言位域的使用与注意事项
  • 2017-05-28用VC++6.0实现石头剪刀布游戏的程序
  • 2017-05-28C++ 赋值构造函数注意点介绍
  • 2017-05-28C++函数重载的深入解析
  • 2017-05-28最长公共子字符串的使用分析
  • 2017-05-28堆排序算法(选择排序改进)
  • 2017-05-28C++运算符重载 成员函数与友元函数详解
  • 2017-05-28关于背包问题的一些理解和应用
  • 2017-05-28字符串的模式匹配详解--BF算法与KMP算法
  • 2017-05-28C语言切割多层字符串(strtok_r strtok使用方法)

文章分类

  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号

最近更新的内容

    • 理解C++编程中的std::function函数封装
    • 浅谈C语言编程中程序的一些基本的编写优化技巧
    • c++回调之利用函数指针示例
    • C++ 冒泡排序数据结构、算法及改进算法
    • 用C语言判断一个二叉树是否为另一个的子结构
    • C语言实现字符转unix时间戳的简单实例
    • C语言实现两个递减数列中寻找某一个数
    • linux C++ 获取文件绝对路径的实例代码
    • 解析C++中不能重载为友元函数的四个运算符
    • 基于C语言指令的深入分析

关于我们 - 联系我们 - 免责声明 - 网站地图

©2020-2025 All Rights Reserved. linkedu.com 版权所有