【c++ primer】【18.2.1】命名空间的定义

  一个命名空间包含两部分:首先是关键字namespace,随后是命名空间的名字。在命名空间名字后面是一系列由花括号括起来的声明和定义。只要能出现在全局作用域中的声明就能置于命名空间内,主要包括:类、变量(及其初始化操作)、函数(及其定义)、模板及其它命名空间: 

namespace cplusplus_primer
{
    class Sales_data {/* ... */};
    Sales_data operator+(const Sales_data&, const Sales_data &);
    class Query {/* ... */};
    class Query_base {/* ... */};
} //命名空间结束后无须分号,这一点跟快类似

上面的代码定义了一个名为cplusplus_primer的命名空间,该命名空间包含四个成员:三个类和一个重载+运算符。

  和其它名字一样,命名空间的名字也必须在定义它的作用域内保持唯一。命名空间既可以定义在全局作用域内,也可以定义在其它命名空间中,但是不能定义在函数或类的内部。

每个命名空间都是一个作用域

  和其它作用域类似,命名空间中的每个名字都必须表示该空间的唯一实体。因为不同的命名空间的作用域不同,所以在不同的命名空间内可以有相同的名字。

  定义在某个命名空间中的名字可以被该命名空间内的其它成员直接访问,也可以被这些成员内嵌作用域的任何单位访问。位于该命名空间之外的代码则必须明确指出所用的名字属于哪个命名空间:

cplusplus_primer::Query q = cplusplus_primer::Query("hello");

  如果其它命名空间(比如说AddisonWesley)也提供了一个名为Query的类,并且希望我们使用这个类代替cplusplus_primer中定义的同名类,则可以按照如下方式修改代码:

AddisonWesley::Query q = AddisonWesley::Query("hello");

命名空间不是连续的

  命名空间可以定义在几个不同的部分,这一点与其它作用域不太一样。编写如下命名空间的定义:

namespace nsp
{
    //相关声明
}

可能是定义了一个名为nsp的命名空间,也可能是为已经存在的命名空间添加一些新成员。如果之前没有nsp的命名空间定义,则上述代码创建一个新的命名空间;否则上述代码打开已经存在的命名空间定义并为其添加一些新成员的声明。

  命名空间可以是不连续的特性使得我们可以将几个独立的接口和实现文件组成一个命名空间。此时,命名空间的组织方式类似于我们管理自定义类及函数的方式:

  • 命名空间的一部分成员的作用是定义类,以及声明作为接口的函数及对象,则这些成员应该置于头文件中,这些头文件将被包含在使用了这些成员的文件中。
  • 命名空间成员的定义部分则置于另外的源文件中。

在程序中某些实体只能定义一次:如非内联函数、静态数据成员、变量等,命名空间中定义的名字也需要满足这一要求,我们可以通过上面的方式组织命名空间并达到目的。这种接口和实现分离的机制确保我们所需的函数和其它名字只定义一次,而只要是用到这些实体的地方都能看到对于实体名字的声明。

定义本书的命名空间

  通过使用上述接口与实现分离的机制,我们可以将cplusplus_primer库定义在几个不同的文件中。Sales_data类的声明及其函数将置于Sales_data.h头文件中,Query将置于Query.h头文件中,以此类推。对应的实现文件将分别是Sales_data.cc和Query.cc:

// --- Sales_data.h ---
// #include应该出现在打开命名空间的操作之前
#include <string>
namespace cplusplus_primer {
    class Sales_data { /* ... */ };
    Sales_data operator+(const Sales_data&, const Sales_data&);
    //Sales_data其它接口函数的声明
}
// ---Sales_data.cc ---
// 确保#include出现在打开命名空间的操作之前
#include "Sales_data.h"

namespace cplusplus_primer {
//Sales_data成员及重载运算符的定义
}

  程序如果使用我们定义的库,必须包含必要的头文件,这些头文件中的名字定义在命名空间cplusplus_primer内:

// --- user.cc ---
// Sales_data.h头文件的名字位于命名空间cplusplus_primer中
#include "Sales_data.h"
int main()
{
    using cplusplus_primer::Sales_data;
    Sales_data trans1, trans2;
    // ...
    //return 0;
}

这种程序的组织方式提供了开发者和库用户所需的模块性。每个类仍组织在自己的接口和实现文件中,一个类的用户不必编译与其它类相关的名字。我们对用户隐藏了实现细节,同时允许文件Sales_data.cc和user.cc被编译并链接成一个程序而不会产生任何编译时错误或链接时错误。库的开发者可以分别实现每个类,相互之间没有干扰。

  有一点需要注意,在通常情况下,我们不把#include放在命名空间内部。如果我们这么做了,隐含的意思是把头文件中所有的名字定义成该命名空间的成员。例如,如果Sales_data.h在包含string头文件之前就已经打开了命名空间cplusplus_primer,则程序将出错,i那位这么做意味着我们试图将命名空间std嵌套在cplusplus_primer中。

原文地址:https://www.cnblogs.com/bootblack/p/11429842.html

时间: 2024-10-09 23:17:58

【c++ primer】【18.2.1】命名空间的定义的相关文章

C++ Primer 学习笔记_66_面向对象编程 --定义基类和派生类[续]

算法旨在用尽可能简单的思路解决问题,理解算法也应该是一个越看越简单的过程,当你看到算法里的一串概念,或者一大坨代码,第一感觉是复杂,此时不妨从例子入手,通过一个简单的例子,并编程实现,这个过程其实就可以理解清楚算法里的最重要的思想,之后扩展,对算法的引理或者更复杂的情况,对算法进行改进.最后,再考虑时间和空间复杂度的问题. 了解这个算法是源于在Network Alignment问题中,图论算法用得比较多,而对于alignment,特别是pairwise alignment, 又经常遇到maxim

命名空间的定义

命名空间是一个容器,这个容器主要是为了识别其下的类和函数.一旦定义了命名空间,它下面的代码就属于这个命名空间了,所以命名空间的定义要在代码的最开始行. 对于同一个包来说,同一个命名空间或者子命名空间的代码没有必要在一个 PHP 文件中定义,子命名空间下的代码是为了完成特定模块的工作,组合起来就是一个包完整的命名空间. 假如编写的代码没有定义命名空间,那说明它属于全局的命名空间(\ 符号),所以能够直接引用类或者函数(不用添加 \ 符号).

在命名空间下定义类型

如果定义的类型要用于其他.NET 语言,应该把它们放在命名空间下,而不是模块中.这是因为模块在被编译成 C# 或其他.NET 语言时,被处理成类,在模块中定义的任何类型都成为这个类型内部的类.虽然对于 C# 来说,这并不是什么大问题,但是,如果用命名空间代替模块,C# 客户端代码看起来会更清晰.这是因为在 C# 中,只用using 语句导入(open)命名空间,而如果是在模块中的类型,在 C# 中使用时,就必须把模块名作为前缀. 让我们看一下这样的例子.下面的例子定义了类TheClass,它是在

C++ Primer 学习笔记_66_面向对象编程 -定义基类跟派生类[续]

面向对象编程 --定义基类和派生类[续] 四.virtual与其他成员函数 C++中的函数调用默认不使用动态绑定.要触发动态绑定,必须满足两个条件: 1)只有指定为虚函数的成员函数才能进行动态绑定,成员函数默认为非虚函数,非虚函数不进行动态绑定. 2)必须通过基类类型的引用或指针进行函数调用. 1.从派生类到基类的转换 因为每个派生类对象都包含基类部分,所以可以将基类类型的引用绑定到派生类对象的基类部分可以用指向基类的指针指向派生类对象: void print_total(const Item_

C++ Primer 学习笔记_93_用于大型程序的工具 --命名空间[续2]

用于大型程序的工具 --命名空间[续2] 五.类.命名空间和作用域 名字的可见性穿过任意嵌套作用域,直到引入名字的块的末尾. 对命名空间内部使用的名字的查找遵循常规C++查找规则:当查找名字的时候,通过外围作用域外查找.对命名空间内部使用的名字而言,外围作用域可能是一个或多个嵌套的命名空间,最终以全包围的全局命名空间结束.只考虑已经在使用点之前声明的名字,而该使用仍在开放的块中: namespace A { int i; namespace B { int i; int j; int f1()

C++ Primer 学习笔记_94_用于大型程序的工具 --命名空间[续3]

用于大型程序的工具 --命名空间[续3] 六.重载与命名空间 正如我们所见,每个命名空间维持自己的作用域,因此,作为两个不同命名空间的成员的函数不能互相重载.但是,给定命名空间可以包含一组重载函数成员. 1.候选函数与命名空间 命名空间对函数匹配有两个影响.一个影响是明显的:using声明或using 指示可以将函数加到候选集合.另一个影响则微妙得多. 正如前节所见,有一个或多个类类型形参的函数的名字查找包括定义每个形参类型的命名空间.这个规则还影响怎样确定候选集合,为找候选函数而查找定义形参类

C++ Primer 学习笔记_91_用于大型程序的工具 --命名空间

用于大型程序的工具 --命名空间 引言: 在一个给定作用域中定义的每个名字在该作用域中必须是唯一的,对庞大.复杂的应用程序而言,这个要求可能难以满足.这样的应用程序的全局作用域中一般有许多名字定义.由独立开发的库构成的复杂程序更有可能遇到名字冲突 -- 同样的名字既可能在我们自己的代码中使用,也可能(更常见地)在独立供应商提供的代码中使用. 库倾向于定义许多全局名字 -- 主要是模板名.类型名或函数名.在使用来自多个供应商的库编写应用程序的时候,这些名字中有一些几乎不可避免地会发生冲突,这种名字

C++ Primer 学习笔记_92_用于大型程序的工具 --命名空间[续1]

用于大型程序的工具 --命名空间[续1] 二.嵌套命名空间 一个嵌套命名空间即是一个嵌套作用域 -- 其作用域嵌套在包含它的命名空间内部.嵌套命名空间中的名字遵循常规规则:外围命名空间中声明的名字被嵌套命名空间中同一名字的声明所屏蔽.嵌套命名空间内部定义的名字局部于该命名空间.外围命名空间之外的代码只能通过限定名引用嵌套命名空间中的名字. 嵌套命名空间可以改进库中代码的组织: namespace cplusplus_primer { namespace QueryLib { class Quer

C++ Primer 学习笔记_92_用来大型程序的工具 -命名空间[续1]

用于大型程序的工具 --命名空间[续1] 二.嵌套命名空间 一个嵌套命名空间即是一个嵌套作用域 -- 其作用域嵌套在包含它的命名空间内部.嵌套命名空间中的名字遵循常规规则:外围命名空间中声明的名字被嵌套命名空间中同一名字的声明所屏蔽.嵌套命名空间内部定义的名字局部于该命名空间.外围命名空间之外的代码只能通过限定名引用嵌套命名空间中的名字. 嵌套命名空间可以改进库中代码的组织: namespace cplusplus_primer { namespace QueryLib { class Quer