热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

名字空间的含义及作用

名字空间是为了防止名字污染在标准C++中引入的。它可以将其中定义的名字隐藏起来,不同的名字空间中可以有相同的名字而互不干扰,使用时用域操作符(::)来引用。namespace名字{

名字空间是为了防止名字污染在标准 C++ 中引入的。
它可以将其中定义的名字隐藏起来,不同的名字空间中可以有相同的名字而互不干扰,使用时用域操作符(::)来引用。
namespace 名字
{
   定义的数据;
   定义的函数;
   也可以是定义的类。。。。。。


}

在应用的时候 使用这些数据和函数名称太麻烦
给定义在同一德的名字空间内
不用繁琐的去重新书写和定义
用名字空间就可以了
我觉得有点像类  又有点像 头文件 

使用方法有以下三种:
1> using namespace sdm;
然后你就可以使用变量temp:
temp=9;
还可以使用sdm中的其他每一个成员。
2>using sdm::temp;
在这个文件中只能使用sdm中的temp这个变量。
3>你在使用时直接使用sdm::temp:
cout<使用其它的成员也这样调用。

 
Top
 
 回复人: oyxiaoyu0(小雨仔) ( ) 信誉:100  2002-08-19 11:07:15Z  得分:0 
 
 
?
可以参考以下资料!


--------------------------------------------------------------------------------
 


条款28: 划分全局名字空间

全局空间最大的问题在于它本身仅有一个。在大的软件项目中,经常会有不少人把他们定义的名字都放在这个单一的空间中,从而不可避免地导致名字冲突。例如,假设library1.h定义了一些常量,其中包括:

const double lib_version = 1.204;

类似的,library2.h也定义了:

const int lib_version = 3;

很显然,如果某个程序想同时包含library1.h和library2.h就会有问题。对于这类问题,你除了嘴里骂几句,或给作者发报复性邮件,或自己编辑头文件来消除名字冲突外,也没其它什么办法。

但是,作为程序员,你可以尽力使自己写的程序库不给别人带来这些问题。例如,可以预先想一些不大可能造成冲突的某种前缀,加在每个全局符号前。当然得承认,这样组合起来的标识符看起来不是那么令人舒服。

另一个比较好的方法是使用c++ namespace。namespace本质上和使用前缀的方法一样,只不过避免了别人总是看到前缀而已。所以,不要这么做:

const double sdmbook_version = 2.0;      // 在这个程序库中,
                                         // 每个符号以"sdm"开头
class sdmhandle { ... };                

sdmhandle& sdmgethandle();             // 为什么函数要这样声明?
                                       // 参见条款47

而要这么做:

namespace sdm {
  const double book_version = 2.0;
  class handle { ... };
  handle& gethandle();
}

用户于是可以通过三种方法来访问这一名字空间里的符号:将名字空间中的所有符号全部引入到某一用户空间;将部分符号引入到某一用户空间;或通过修饰符显式地一次性使用某个符号:

void f1()
{
  using namespace sdm;           // 使得sdm中的所有符号不用加
                                 // 修饰符就可以使用

  cout <  ...

  handle h = gethandle();        // handle解释为sdm::handle,
                                 // gethandle解释为sdm::gethandle
  ...                           

}

void f2()
{
  using sdm::book_version;        // 使得仅book_version不用加
                                 // 修饰符就可以使用

  cout <                                  // sdm::book_version
  ...

  handle h = gethandle();         // 错误! handle和gethandle
                                  // 都没有引入到本空间
  ...                            

}

void f3()
{
  cout <                                  // 在本语句有效
  ...                            

  double d = book_version;        // 错误! book_version
                                  // 不在本空间

  handle h = gethandle();         // 错误! handle和gethandle
                                  // 都没有引入到本空间
  ...                           

}

(有些名字空间没有名字。这种没命名的名字空间一般用于限制名字空间内部元素的可见性。详见条款m31。)

名字空间带来的最大的好处之一在于:潜在的二义不会造成错误(参见条款26)。所以,从多个不同的名字空间引入同一个符号名不会造成冲突(假如确实真的从不使用这个符号的话)。例如,除了名字空间sdm外,假如还要用到下面这个名字空间:

namespace acmewindowsystem {

  ...

  typedef int handle;

  ...

}

只要不引用符号handle,使用sdm和acmewindowsystem时就不会有冲突。假如真的要引用,可以明确地指明是哪个名字空间的handle:

void f()
{
  using namespace sdm;                 // 引入sdm里的所有符号
  using namespace acmewindowsystem;    // 引入acme里的所有符号

  ...                                  // 自由地引用sdm
                                       // 和acme里除handle之外
                                       // 的其它符号

  handle h;                            // 错误! 哪个handle?

  sdm::handle h1;                      // 正确, 没有二义

  acmewindowsystem::handle h2;         // 也没有二义

  ...

}

假如用常规的基于头文件的方法来做,只是简单地包含sdm.h和acme.h,这样的话,由于handle有多个定义,编译将不能通过。

名字空间的概念加入到c++标准的时间相对较晚,所以有些人会认为它不太重要,可有可无。但这种想法是错误的,因为c++标准库(参见条款49)里几乎所有的东西都存在于名字空间std之中。这可能令你不以为然,但它却以一种直接的方式影响到你:这就是为什么c++提供了那些看起来很有趣的、没有扩展名的头文件,如, 等。详细介绍参见条款49。

由于名字空间的概念引入的时间相对较晚,有些编译器可能不支持。就算是这样,那也没理由污染全局名字空间,因为可以用struct来近似实现namespace。可以这样做:先创建一个结构用以保存全局符号名,然后将这些全局符号名作为静态成员放入结构中:

// 用于模拟名字空间的一个结构的定义
struct sdm {
  static const double book_version;
  class handle { ... };
  static handle& gethandle();
};

const double sdm::book_version = 2.0;      // 静态成员的定义

现在,如果有人想访问这些全局符号名,只用简单地在它们前面加上结构名作为前缀:

void f()
{
  cout <

  ...

  sdm::handle h = sdm::gethandle();

  ...
}

但是,如果全局范围内实际上没有名字冲突,用户就会觉得加修饰符麻烦而多余。幸运的是,还是有办法来让用户选择使用它们或忽略它们。

对于类型名,可以用类型定义(typedef)来显式地去掉空间引用。例如,假设结构s(模拟的名字空间)内有个类型名t,可以这样用typedef来使得t成为s::t的同义词:

typedef sdm::handle handle;

对于结构中的每个(静态)对象x,可以提供一个(全局)引用x,并初始化为s::x:

const double& book_version = sdm::book_version;

老实说,如果读了条款47,你就会不喜欢定义一个象book_version这样的非局部静态对象。(你就会用条款47中所介绍的函数来取代这样的对象)

处理函数的方法和处理对象一样,但要注意,即使定义函数的引用是合法的,但代码的维护者会更喜欢你使用函数指针:

sdm::handle& (* const gethandle)() =      // gethandle是指向sdm::gethandle
  sdm::gethandle;                         // 的const 指针 (见条款21)

注意gethandle是一个常指针。因为你当然不想让你的用户将它指向别的什么东西,而不是sdm::gethandle,对不对?

(如果真想知道怎么定义一个函数的引用,看看下面:

sdm::handle& (&gethandle)() =      // gethandle是指向
  sdm::gethandle;                  // sdm::gethandle的引用

我个人认为这样的做法也很好,但你可能以前从没见到过。除了初始化的方式外,函数的引用和函数的常指针在行为上完全相同,只是函数指针更易于理解。)

有了上面的类型定义和引用,那些不会遭遇全局名字冲突的用户就会使用没有修饰符的类型和对象名;相反,那些有全局名字冲突的用户就会忽略类型和引用的定义,代之以带修饰符的符号名。还要注意的是,不是所有用户都想使用这种简写名,所以要把类型定义和引用放在一个单独的头文件中,不要把它和(模拟namespace的)结构的定义混在一起。

struct是namespace的很好的近似,但实际上还是相差很远。它在很多方面很欠缺,其中很明显的一点是对运算符的处理。如果运算符被定义为结构的静态成员,它就只能通过函数调用来使用,而不能象常规的运算符所设计的那样,可以通过自然的中缀语法来使用:

// 定义一个模拟名字空间的结构,结构内部包含widgets的类型
// 和函数。widgets对象支持operator+进行加法运算
struct widgets {
  class widget { ... };


  // 参见条款21:为什么返回const
  static const widget operator+(const widget& lhs,
                                const widget& rhs);

  ...

};

// 为上面所述的widge和operator+
// 建立全局(无修饰符的)名称

typedef widgets::widget widget;


const widget (* const operator+)(const widget&,        // 错误!
                                 const widget&);       // operator+不能是指针名
 

widget w1, w2, sum;

sum = w1 + w2;                           // 错误! 本空间没有声明
                                         // 参数为widgets 的operator+

sum = widgets::operator+(w1, w2);        // 合法, 但不是
                                         // "自然"的语法

正因为这些限制,所以一旦编译器支持,就要尽早使用真正的名字空间。

 


推荐阅读
  • Android源码深入理解JNI技术的概述和应用
    本文介绍了Android源码中的JNI技术,包括概述和应用。JNI是Java Native Interface的缩写,是一种技术,可以实现Java程序调用Native语言写的函数,以及Native程序调用Java层的函数。在Android平台上,JNI充当了连接Java世界和Native世界的桥梁。本文通过分析Android源码中的相关文件和位置,深入探讨了JNI技术在Android开发中的重要性和应用场景。 ... [详细]
  • C语言注释工具及快捷键,删除C语言注释工具的实现思路
    本文介绍了C语言中注释的两种方式以及注释的作用,提供了删除C语言注释的工具实现思路,并分享了C语言中注释的快捷键操作方法。 ... [详细]
  • Java学习笔记之面向对象编程(OOP)
    本文介绍了Java学习笔记中的面向对象编程(OOP)内容,包括OOP的三大特性(封装、继承、多态)和五大原则(单一职责原则、开放封闭原则、里式替换原则、依赖倒置原则)。通过学习OOP,可以提高代码复用性、拓展性和安全性。 ... [详细]
  • Java在运行已编译完成的类时,是通过java虚拟机来装载和执行的,java虚拟机通过操作系统命令JAVA_HOMEbinjava–option来启 ... [详细]
  • 向QTextEdit拖放文件的方法及实现步骤
    本文介绍了在使用QTextEdit时如何实现拖放文件的功能,包括相关的方法和实现步骤。通过重写dragEnterEvent和dropEvent函数,并结合QMimeData和QUrl等类,可以轻松实现向QTextEdit拖放文件的功能。详细的代码实现和说明可以参考本文提供的示例代码。 ... [详细]
  • 本文分享了一个关于在C#中使用异步代码的问题,作者在控制台中运行时代码正常工作,但在Windows窗体中却无法正常工作。作者尝试搜索局域网上的主机,但在窗体中计数器没有减少。文章提供了相关的代码和解决思路。 ... [详细]
  • 本文讨论了如何优化解决hdu 1003 java题目的动态规划方法,通过分析加法规则和最大和的性质,提出了一种优化的思路。具体方法是,当从1加到n为负时,即sum(1,n)sum(n,s),可以继续加法计算。同时,还考虑了两种特殊情况:都是负数的情况和有0的情况。最后,通过使用Scanner类来获取输入数据。 ... [详细]
  • 在说Hibernate映射前,我们先来了解下对象关系映射ORM。ORM的实现思想就是将关系数据库中表的数据映射成对象,以对象的形式展现。这样开发人员就可以把对数据库的操作转化为对 ... [详细]
  • 知识图谱——机器大脑中的知识库
    本文介绍了知识图谱在机器大脑中的应用,以及搜索引擎在知识图谱方面的发展。以谷歌知识图谱为例,说明了知识图谱的智能化特点。通过搜索引擎用户可以获取更加智能化的答案,如搜索关键词"Marie Curie",会得到居里夫人的详细信息以及与之相关的历史人物。知识图谱的出现引起了搜索引擎行业的变革,不仅美国的微软必应,中国的百度、搜狗等搜索引擎公司也纷纷推出了自己的知识图谱。 ... [详细]
  • 猜字母游戏
    猜字母游戏猜字母游戏——设计数据结构猜字母游戏——设计程序结构猜字母游戏——实现字母生成方法猜字母游戏——实现字母检测方法猜字母游戏——实现主方法1猜字母游戏——设计数据结构1.1 ... [详细]
  • 本文介绍了在Windows环境下如何配置php+apache环境,包括下载php7和apache2.4、安装vc2015运行时环境、启动php7和apache2.4等步骤。希望对需要搭建php7环境的读者有一定的参考价值。摘要长度为169字。 ... [详细]
  • 前景:当UI一个查询条件为多项选择,或录入多个条件的时候,比如查询所有名称里面包含以下动态条件,需要模糊查询里面每一项时比如是这样一个数组条件:newstring[]{兴业银行, ... [详细]
  • C++字符字符串处理及字符集编码方案
    本文介绍了C++中字符字符串处理的问题,并详细解释了字符集编码方案,包括UNICODE、Windows apps采用的UTF-16编码、ASCII、SBCS和DBCS编码方案。同时说明了ANSI C标准和Windows中的字符/字符串数据类型实现。文章还提到了在编译时需要定义UNICODE宏以支持unicode编码,否则将使用windows code page编译。最后,给出了相关的头文件和数据类型定义。 ... [详细]
  • 本文介绍了iOS数据库Sqlite的SQL语句分类和常见约束关键字。SQL语句分为DDL、DML和DQL三种类型,其中DDL语句用于定义、删除和修改数据表,关键字包括create、drop和alter。常见约束关键字包括if not exists、if exists、primary key、autoincrement、not null和default。此外,还介绍了常见的数据库数据类型,包括integer、text和real。 ... [详细]
  • 本文介绍了深入浅出Linux设备驱动编程的重要性,以及两种加载和删除Linux内核模块的方法。通过一个内核模块的例子,展示了模块的编译和加载过程,并讨论了模块对内核大小的控制。深入理解Linux设备驱动编程对于开发者来说非常重要。 ... [详细]
author-avatar
mobiledu2502911403
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有