原创 C++做用域 (一)

1概述

在全部的计算机程序中,一个基本的目标是操做一些数据,而后得到一些结果。为了操做这些数据,须要为这些数据分配一段内存,咱们能够将这段内存称为变量。为了方便操做,以及程序可读性方面的考虑,须要使用一个有意义的名称来引用这段内存,这个名称就是变量名。ios

将名称和一段内存关联起来的工做能够分红两个阶段来进行,分别是变量的声明和定义。在变量声明的时候,只是引入了一个名称,该名称并无和一段特定的内存关联。也就是说,在声明变量的时候,只是引入了一个助记符,并无执行内存分配。在定义变量的时候,将前面声明过程当中引入的名称关联到了一段特定的内存,内存的大小由变量的类型决定。也就是说,在定义变量的时候,真正执行了内存分配。在有的状况下,变量的声明和定义是须要分开进行的,如:全局变量的声明和定义,能够在多个文件中使用该变量;而在某些状况下,使用一个语句就能够完成变量的声明和定义,如:局部变量的声明和定义。只须要在一个文件中使用该变量。程序员

在C++程序中,当声明并定义了一个变量之后,须要关注以下两个问题:算法

  1. 由声明引入的变量名能够用在什么地方,如何进行名字解析;
  2. 由定义分配的内存的生命周期是多少。

为了解决这两个问题,就须要引入做用域的概念。做用域是C++程序中的一段区域,通常用正反两个花括号来界定它的范围。在同一个做用域范围内,一个名称只能惟一关联到一个实体,这个实体能够是变量,函数,类型,模版等。也就是说,在同一做用域范围内,不一样的实体必须对应不一样的名称,绝对不容许出现两个不一样的实体对应同一个相同的名称的状况。一个名称能够和不一样做用域中的不一样实体相对应。也就是说,对于同一个名称,在不一样的做用域中能够重复使用。数组

在本文的后续部分,将对各类类型的做用域进行描述,而且介绍在做用域中进行名字解析的规则。缓存

2做用域的分类

2.1概述

咱们能够将整个C++程序(在程序中包括各类类型,函数,模版,变量等,而且分布在不少个*.cpp文件中)当作一个很大的总体区域。为了方便对C++程序中已经定义的各类类型,函数,模版,变量的管理,能够把这片大的区域划分红一片片小的命名区段。而后根据各个类型,函数,模版,变量的功能以及用途等,再把这些类型,函数,模版,变量等分别放置在不一样的区段中。这些小的区段叫作做用域,C++程序支持四种形式的做用域,分别是:名字空间做用域,类域,局部做用域,语句做用域。安全

名字空间做用域就是程序员利用名字空间定义在C++程序中划分出来的一块比较大的程序区段。在该程序区段内部,能够定义类型,函数,模版,变量。名字空间做用域能够跨越多个*.cpp文件而存在。在名字空间做用域内部还能够继续定义其余的名字空间做用域,也就是说,名字空间做用域是能够互相嵌套的。数据结构

全局做用域是C++程序最外层的名字空间做用域,也是最大的名字空间做用域。全局做用域自然存在于C++程序中,它不须要由程序员人为地定义。在全局做用域内部,能够包含其余的,由程序员定义的名字空间做用域,以及没有包含在其余名字空间做用域中的类型,函数,模版,变量。在全局做用域中定义的变量是全局变量,在全局做用域中定义的函数是全局函数。函数

在C++程序中,每定义一个类就会引入一个类域。类体所包含的范围就是类域的范围,在类中定义的全部成员都属于该类域。类域位于名字空间做用域内部,该名字空间做用域多是全局做用域,也多是用户定义的名字空间做用域。工具

每个函数体内部都是一个局部做用域。该做用域起始于函数体的左花括号“{”,结束于函数体的右花括号“}”。每个函数都有一个独立的局部做用域。在局部做用域内定义的变量都是局部变量。spa

在C++程序中,当要求使用单个语句,但程序逻辑却须要不止一个单个语句的时候,咱们可使用复合语句。复合语句一般被称为块,是用花括号括起来的一些单个语句的集合。在复合语句花括号内部的区段也属于局部做用域。

有些语句存在控制结构,而且容许在控制结构中定义变量。如:

 

示例一:

for ( int K = 0; K < 100;K++ )

  cout << K;     //该行语句属于语句做用域范围,K仅在这一行有效。

示例二:

for (int K = 0; K < 100;K++)

{

   … //其余代码

   Cout << k;   //花括号内部是复合语句,都属于语句做用域。K在整个花括号内有效。

   … //其余代码

}

 

    从控制语句的开始到控制语句结束这一段区域被称为语句做用域。在该控制结构中定义的变量,仅在该语句做用域内有效。如:示例二中,K在花括号内有效,或者示例一中,仅在语句“cout << K;”中有效。语句做用域是最小的做用域。

全局做用域,名字空间做用域,类域,局部做用域,语句做用域之间的关系以下图所示:

 

从上图能够看出,在全局做用域中,定义了两个名字空间H和K。名字空间H又分别位于两个CPP文件A和B中。因而可知,名字空间做用域是能够跨越CPP文件的。在名字空间K中,除了定义了类型外,又定义了一个名字空间N,因此说,名字空间之间是能够互相嵌套的。另外,在名字空间中能够定义类,函数,变量,模版等。

在全局做用域中,除了定义的名字空间H和K外,又定义了一个类D,以及全局函数,全局变量和模版。在类D中,定义了一些成员函数,所以引出了局部做用域。在局部做用域中,若是存在控制语句,就会存在语句做用域。

在各类做用域中定义的变量或对象,其生命周期从该变量被定义开始,直到该做用域结束。如:在全局做用域中定义的变量,其生命周期是整个程序的生命周期,程序运行结束,该变量被释放;在局部做用域中定义的变量,其生命周期是从定义该变量开始,直到该函数执行完毕。

2.2名字空间做用域

2.2.1名字空间的意义

使用名字空间能够在必定程度上解决命名冲突的问题。假设没有名字空间,那么在C++程序中,全部的实体,如:函数,类型,变量,模版等,都必须被放置在全局域中做为全局实体而出现。在全局域中,这些实体必须具备惟一的名称,不容许存在多个实体同名的状况。所以,当在全局域中引入一些第三方开发的类库的时候,必需要保证第三方类库中命名的实体与全局域中命名的实体在命名方面不冲突。可是,这是很难保证的。为了解决这个问题,就引入了名字空间的概念。

第三方开发方在开发类库的时候,能够首先声明一个名字空间,每个用户声明的名称空间都表明一个不一样的名字空间域。在该名字空间中,能够包含嵌套其余的名称空间,以及函数,类型,变量,模版等的声明和定义。在该名称空间内部声明的实体被称为名称空间成员。用户在名字空间中声明的每一个实体的名字必须是惟一的,不容许重名。由于在不一样用户声明的名字空间中引入了不一样的域,因此在这些由不一样用户声明的名字空间中可使用相同的名称。经过这种方式解决了命名冲突的问题。

在使用名字空间中的成员的时候,名字空间成员的名字会自动与该名字空间重合,或者说被其限定修饰。如:在名字空间A中声明的类B,它的名字是:A::B。

2.2.2名字空间的定义

用户声明的名字空间以namespace关键字开头,后面是名字空间的名称。名字空间的范围以花括号界定,具体的格式以下:

namespace mySpace //mySpace是名字空间的名称

{

   Class myClass { … }; //类定义

   Int myFunction(int para1,int para2); //函数的声明

   Extern double myVar; //变量的声明

}

    在上面的示例中,声明了一个名称为mySpace的名字空间,该名字空间的做用域由花括号界定,在花括号内部的部分都属于该名字空间的做用域。在该名字空间中,定义了一个类:myClass,声明了一个函数:myFunction,以及一个变量myVar。它们都是该名字空间的成员。

   

用户声明的名字空间能够位于全局做用域中,也能够位于其余的名字空间的做用域中。在当前的做用域中,名字空间的名称是惟一的,不能与其类型的实体重名。

在同一个做用域中,能够屡次声明相同名称的名字空间。在这种状况下,将会实现名字空间的累加。好比,A.h头文件和A.cpp源文件都位于全局做用域中,在这两个文件中分别声明以下的名字空间:

A. h文件的代码实现:

namespace mySpace //在这里实现了函数和变量的声明,属于接口部分。

{

   Int AddData (int para1,int para2); //函数的声明

   Extern double myVar;  //变量的声明

}

B.cpp文件的代码实现:

Include “A.h”

namespace mySpace // 在这里实现了函数和变量的定义,属于实现部分。

{

   Int AddData(int Para1,int Para2) //函数的定义

   {

      Return Para1+Para2;

   }

 

    Double myVar = 3.14;  //变量的定义,并初始化。

}

在这里,存在这样一个规则:在同一个做用域中,若是新声明的一个名字空间的名称与前面声明过的名字空间的名称同名,那么这个后声明的名字空间就是前面声明的名字空间的累加,这两部份内容属于同一个名字空间;若是新声明的这个名字空间不与当前做用域中任何名字空间同名,那么就会定义一个新的名字空间。

在上面的示例中,A.h和A.cpp文件位于全局做用域中。在全局做用域中,两次声明的名字空间具备相同的名称:mySpace。所以,认为这两次声明的名字空间属于同一个名字空间。

经过对上面所描述的规则的使用,在程序设计的时候,能够根据须要,将名字空间的声明拆分红若干个部分来实现,只要这几个部分的声明都在同一个做用域中便可。这个规则的一个典型应用就是:实现接口和具体实现的分离。

在上面的示例中,咱们将函数AddData和变量myVar的声明放在了A.h头文件中,而将它们的定义放在了另一个A.cpp的源文件中。 A.h头文件实现的是函数库的接口的,而A.cpp文件中的内容则是针对接口的实现。所以,在程序设计和开发的时候,这两部份内容能够分别由不一样的人在不一样的时间实现。经过这种方式,实现了接口和具体实现分离的原则。

 

2.2.3名字空间成员的定义

当定义了名字空间之后,就能够想名字空间中添加成员。这些被添加的成员能够是:类型,函数,变量,模版等。能够经过两种方式向名字空间中添加成员。

第一种方式是:在定义名字空间的同时,在名字空间的花括号内直接完成名字空间成员的定义。也就是说,不管名字空间的定义是采用累加的形式,仍是该名字空间分布在多个物理文件中,名字空间成员的声明和定义都在名字空间内部进行。具体示例以下:

方式一:在名字空间中直接完成成员的定义。成员的定义不在划分为声明和定义两部分。

Namespace mySpace

{

   Double myVar = 3.14;

   Int myFunction(int Para1)

   {

       Return Para1*10;

   }

}

方式二:在名字空间中先完成成员的声明,而后采用名字空间累加的方式,在其余部分完成成员的定义。这个“其余部分”,能够是其余的物理文件,也能够是同一个物理文件。

Namespace mySpace

{

Extern double myVar;

Int myFunction(int Para1);

}

 

Namespace mySpace

{

Double myVar = 3.14;

Int myFunction(int Para1)

{

   Return Para1*10;

}

}

在上面的代码中,在定义了名字空间的同时(不管是采用累加方式,仍是一次性完成),在名字空间内部完成了函数myFunction和变量myVar的定义。名字空间的定义和名字空间成员的定义同步完成。

第二种方式是:在定义名字空间的时候,仅仅在名字空间中完成对名字空间成员的声明,而名字空间成员的定义在名字空间以外被实现。具体代码以下:

//首先在一个文件中完成名字空间的定义,以及名字空间成员的声明。通常状况下,该文件为头文件(A.h)。

Namespace mySpace

{

Class myClass {….};//声明一个类型

myClass myFunction(myClass Para1);//声明一个函数,该函数返回myClass类型,并以myClass类型为参数。

}

在上面的代码中,完成了对名字空间mySpace的定义,同时在名字空间内部,完成了类myClass的定义,以及对函数myFunction的声明。接下来须要在其余地方,名字空间之外,完成对名字空间成员myFunction函数的定义。具体代码以下:

//实现函数myFunction定义的位置,能够是另一个文件,通常为cpp文件,可是也能够在原来的头文件中(通常不会这么干)。

#include “A.h”

mySpace::myClass mySpace::myFunction(myClass Para1)

{

    //下面完成函数的具体实现。

   …

}

在上面的代码中,咱们能够看到两处差别。一处是函数的返回值类型,myClass被名字空间mySpace限定修饰了;而在函数的参数类型处,myClass直接使用,没有被名字空间mySpace限定修饰。

这里存在这样一个规则:在函数的限定修饰名称“mySpace::myFunction”以后,直到方括号结束的区域都属于mySpace名字空间的做用域范围。也就是上面代码中的红色部分。

也就是说名字空间的做用域可能会有两部分组成,在大多数状况下,名字空间的做用域是由定义名字空间的时候,名字空间体的花括号界定的。可是,当在名字空间以外定义名称空间的成员的时候,在名字空间成员的限定修饰名以后直到结束花括号(” }”),或者分号(;)的部分都属于该名字空间做用域范围。

所以,在上面的代码中,参数的类型不须要被限定修饰,由于那个区域是属于名字空间做用域内的;而函数的返回类型必需要被限定修饰,由于那个区域不属于名字空间的做用域内。

另外还须要注意,在名字空间以外实现名字空间成员的定义的时候,要有一个前提,那就是:名字空间成员的声明必须在名字空间以内实现。

2.2.4名字空间成员的使用

在C++程序中,使用名字空间的方式封装一些函数库或者类库的时候,通常状况下,一般的作法是这样的:首先在一个头文件中定义一个名字空间,而后在该名字空间的定义中声明全部的名字空间成员,如:函数,类型,变量等。以后将这个头文件引入到一个cpp文件中,而且在这个cpp文件中实现全部名字空间成员的定义。具体示例以下:

-----------------A.h------------------------------//头文件名称

namespace myCPlusPlusFunctionsV1.0

{

     Class myClass { …//类成员的声明 }; //定义一个类型

     Extern double myVar; //声明变量

     Void DealClass(myClass*); //声明函数

}

-----------------A.cpp--------------------------//源文件

#include “A.h”

Namespace myCPlusPlusFunctionsV1.0

{

myClass:: myClass() { … // myClass构造函数的实现}

//其余myClass类成员的定义。

double myVar = 3.14;//变量的定义

void DealClass(myClass*pClass)

{

   …//函数的具体实现。

}

}

 

在使用这些函数库或者类库的时候,首先须要将这个定义了该名字空间的头文件引入,而后开始使用该名字空间中的一些成员。在使用名字空间成员的时候,有三种方式:

第一种方式:域操做符方式。经过域操做符加名字空间名称的方式对名字空间成员名进行限定修饰。具体代码以下:

------------------otherCPlusPlusFile.cpp-------------------------

#include “A.h”

Void main()

{

   myCPlusPlusFunctionsV1.0::myClass *pClass = new myCPlusPlusFunctionsV1.0::myClass;

   myCPlusPlusFunctionsV1.01::DealClass(pClass);

}

在上面的代码中,“::”是域操做符。名字空间成员的声明被隐藏在名字空间之中,因此,名称空间的成员名称不会与当前做用域中的对象实体名称产生冲突。在使用名字空间成员的时候,可使用名字空间名+域操做符+名字空间成员名称的方式将名字空间成员引入到当前的做用域中。不然,在当前做用域中,编译器不会找到名字空间的成员。

域操做符也能够被用来引用全局做用域的成员。由于全局做用域没有名称,因此使用以下的符号:

 ::member_name

指向全局名字空间的成员。当全局名字空间成员的名称被局部做用域中的名字隐藏的时候,但又须要在局部做用域中使用全局成员的时候,就可使用这种引用方式。

在上面的示例中,名字空间的名称“myCPlusPlusFunctionsV1.0”比较长,在使用的时候,可能会不方便,所以,C++在处理这个问题的时候,引入了名字空间别名的概念。

    所谓名字空间别名就是为已经定义的名字空间取一个其余的、替代性的名称,一帮状况下,这个名称是简短的,容易记忆的。具体使用方式以下:

 

------------------otherCPlusPlusFile.cpp-------------------------

#include “A.h”

Namespace myC++ = myCPlusPlusFunctionsV1.0;

Void main()

{

   myC++::myClass *pClass = new myC++::myClass;

   myC++::DealClass(pClass);

}

在上面的代码中,为名字空间“myCPlusPlusFunctionsV1.0”定义了一个别名“myC++”。以后在引用该名字空间成员的时候,就可使用该别名。

定义名字空间别名的格式是:以关键字namespace开头,后跟名字空间的别名,而且等于前面定义好的名字空间的名称。

第二种方式:使用using 声明,一次引入一个名字空间成员。

Using 声明的做用是:使一个名字空间成员在当前做用域中可见,可见的范围是从using声明的语句开始,直到当前做用域结束。若是在using声明语句以后,在当前做用域中又嵌套了其余的做用域,那么using声明在当前做用域中的嵌套做用域中也一样有效。

Using声明以关键字using开头,后跟名字空间的成员名称。该成员名称必须是名字空间名称+域操做符+名字空间成员名称形式的限定修饰名称。具体代码以下:

//名字空间的定义

Namespace mySpace

{

Int myFunction(int Para)//在名字空间中定义了一个函数

{

     Return Para*10;

}

}

//在全局做用域中使用using声明,将名字空间成员名引入当前做用域。

Using mySpace::myFunction;

//开始使用名字空间的成员

Void main()

{

   //也能够在此位置使用using声明,即在局部做用域使用using声明。

   myFunction(10);//使用名字空间的成员。由于使用了using声明,因此不须要使用限定修饰的形式。名称myFunction从using声明开始,直到当前做用域结束。

}

在上面的代码中,首先定义了一个名字空间,并在名字空间中定义了一个函数。而后在全局做用域中使用了using声明。以后,在main函数中使用名字空间的成员函数myFucntin。

能够在全局做用域,名字空间做用域,局部做用域中使用using声明。在使用了using 声明之后,一次只能从源名字空间向当前做用域中引入一个名字空间成员,但能够屡次使用using声明。若是该名字空间成员是函数,而且在该名字空间中具备多个重载,那么在使用using声明的时候,全部的重载函数都会被引入到当前的做用域中。被引入的名字空间成员名只在当前做用域中有效,而且名称惟一。这个被引入的名字空间成员名会隐藏当前做用域外围做用域中的同名名称,也会被当前做用域的嵌套做用域中的同名名称隐藏。具体状况见以下代码:

namespace mySpace

{

   Int myIntVar = 10;//定义一个整型变量。名字空间成员。

}

 

Int myIntVar = 100;//全局变量

Int main()

{

Using mySpace::myIntVar;//该using声明隐藏了全局变量myIntVar。

Int k = 10;

K = k + myIntVar;//使用的是名字空间的成员变量,因此k的值等于20.

K = K + ::myIntVar;//这里使用的是全局变量,因此k的值等于110.

{

     Int myIntVar = 50;//在此语句做用域中声明的变量隐藏了前面using声明中引入的变量。

    Int a  = myIntVar ;//a = 50

    Int b  = ::myIntVar;//b = 100;

    Int C  = mySpace::myIntVar;//c = 10;

}

}

使用using声明将名字空间的成员引入到当前做用域的时候,除了重载函数之外,被引入的成员名称不能与当前做用域中定义的对象实体重名,不然会引发错误。

第三种方式:使用using 指示符,一次引入全部名字空间成员。

Using指示符以关键字using 开头后跟关键字namespace,最后是名字空间的名称。该名字空间的名称必须在前面已经定义。其做用域从using指示符开始,直到当前做用域结束。使用using指示符之后,将会把名字空间中的全部成员引入到当前做用域。具体的代码以下:

//定义名字空间

Namespace mySpace

{

Int myFunction(int Para)

{

   Return Para*10;

}

Int myVar = 100;

}

//使用using指示符,将名字空间的全部成员引入到当前做用域。目前是全局做用域。

Using namespace mySpace;

Void main()

{

Int k = myVar + 10;//使用using指示符之后,能够直接使用名字空间中的成员,就好像该//名字空间的成员在当前做用域中定义的同样,不须要限定修饰。

myFunction(k);

}

在上面的代码中,首先定义了一个名字空间mySpace,同时在名字空间中定义了一个函数myFunction,以及一个变量myVar。而后使用using指示符将该名字空间中的成员引入到了全局做用域中。以后,在main函数中使用名字空间的成员,使用的时候,不须要限定修饰,就好像使用当前名字空间中定义的成员同样。

在当前做用域使用using指示符之后,被引用的名字空间将与当前的做用域合并,名字空间中的成员就好像在当前做用域被定义同样。所以,在当前做用域中,不能定义与名称空间成员重名的对象。不然会所以错误。

2.2.6 标准名字空间std

在名字空间的概念被提出以前,在C++中就已经存在了大量的库函数。这些库函数有的是标注C形式的,也有的是标准C++形式的。在声明这些库函数的时候,按照其功能和类别,它们被划分到不少不一样的头文件中,如:iostream.h,complox.h,stdio.h。当名字空间的概念被提出以后,这些库函数被从新整理,将它们的声明和定义放到了名称空间名称为std的名称空间中。它们被称为标准C++库。

可是为了向前兼容之前实现的C++程序,在对这些库函数进行整理的时候,建立了新的头文件,并采用了新的命名规则,以区分原有的库函数。具体的处理方式描述以下:

  1. 对于支持C++的头文件,如:<iostream.h>,在被从新整理以后,它的名称为<iostream>去掉了头文件的扩展名。新的头文件所包含的功能与旧头文件基本相同,可是它们在std名字空间中;
  2. 对于支持C标准的头文件,如:<stdio.h>,在被从新整理以后,它的名称为<cstdio>,在名称的前面加上了前缀字符“C”,并去掉扩展名。新的头文件所包含的功能与旧的头文件基本相同,可是它们在std名字空间中。
  3. 原有旧的C++标准头文件,如<iostream.h>,依然被支持,它们不在名字空间std中;
  4. 原有旧的C标准头文件,如<stdio.h>,依然被支持,它们不在名字空间std中。
      

具体状况以下图所示:

 

在C++标准库中,一共50个头文件,10个分类,其中18个C库功能。与宏相关的名称在全局做用域中定义,其余的在名字空间std中被定义。

   按照分类,C++标准库的详细状况以下表所示:

C1. 标准库中与语言支持功能相关的头文件

头文件

描        述

<cstddef>

定义宏NULL和offsetof,以及其余标准类型size_t和ptrdiff_t。与对应的标准C头文件的区别是,NULL是C++空指针常量的补充定义,宏offsetof接受结构或者联合类型参数,只要他们没有成员指针类型的非静态成员便可。

<limits>

提供与基本数据类型相关的定义。例如,对于每一个数值数据类型,它定义了能够表示出来的最大值和最小值以及二进制数字的位数。

<climits>

提供与基本整数数据类型相关的C样式定义。这些信息的C++样式定义在<limits>中

<cfloat>

提供与基本浮点型数据类型相关的C样式定义。这些信息的C++样式定义在<limits>中

<cstdlib>

提供支持程序启动和终止的宏和函数。这个头文件还声明了许多其余杂项函数,例如搜索和排序函数,从字符串转换为数值等函数。它与对应的标准C头文件stdlib.h不一样,定义了abort(void)。abort()函数还有额外的功能,它不为静态或自动对象调用析构函数,也不调用传给atexit()函数的函数。它还定义了exit()函数的额外功能,能够释放静态对象,以注册的逆序调用用atexit()注册的函数。清除并关闭全部打开的C流,把控制权返回给主机环境。

<new>

支持动态内存分配

<typeinfo>

支持变量在运行期间的类型标识

<exception>

支持异常处理,这是处理程序中可能发生的错误的一种方式

<cstdarg>

支持接受数量可变的参数的函数。即在调用函数时,能够给函数传送数量不等的数据项。它定义了宏va_arg、va_end、va_start以及va_list类型

<csetjmp>

为C样式的非本地跳跃提供函数。这些函数在C++中不经常使用

<csignal>

为中断处理提供C样式支持

C2. 支持流输入/输出的头文件

头文件

描        述

<iostream>

支持标准流cin、cout、cerr和clog的输入和输出,它还支持多字节字符标准流wcin、wcout、wcerr和wclog。

<iomanip>

提供操纵程序,容许改变流的状态,从而改变输出的格式。

<ios>

定义iostream的基类

<istream>

为管理输出流缓存区的输入定义模板类

<ostream>

为管理输出流缓存区的输出定义模板类

<sstream>

支持字符串的流输入输出

<fstream>

支持文件的流输入输出

<iosfwd>

为输入输出对象提供向前的声明

<streambuf>

支持流输入和输出的缓存

<cstdio>

为标准流提供C样式的输入和输出

<cwchar>

支持多字节字符的C样式输入输出

C3. 与诊断功能相关的头文件

头文件

描        述

<stdexcept>

定义标准异常。异常是处理错误的方式

<cassert>

定义断言宏,用于检查运行期间的情形

<cerrno>

支持C样式的错误信息

C4. 定义工具函数的头文件

头文件

描        述

<utility>

定义重载的关系运算符,简化关系运算符的写入,它还定义了pair类型,该类型是一种模板类型,能够存储一对值。这些功能在库的其余地方使用

<functional>

定义了许多函数对象类型和支持函数对象的功能,函数对象是支持operator()()函数调用运算符的任意对象

<memory>

给容器、管理内存的函数和auto_ptr模板类定义标准内存分配器

<ctime>

支持系统时钟函数

C5. 支持字符串处理的头文件

头文件

描        述

<string>

为字符串类型提供支持和定义,包括单字节字符串(由char组成)的string和多字节字符串(由wchar_t组成)

<cctype>

单字节字符类别

<cwctype>

多字节字符类别

<cstring>

为处理非空字节序列和内存块提供函数。这不一样于对应的标准C库头文件,几个C样式字符串的通常C库函数被返回值为const和非const的函数对替代了

<cwchar>

为处理、执行I/O和转换多字节字符序列提供函数,这不一样于对应的标准C库头文件,几个多字节C样式字符串操做的通常C库函数被返回值为const和非const的函数对替代了。

<cstdlib>

为把单字节字符串转换为数值、在多字节字符和多字节字符串之间转换提供函数

C6. 定义容器类的模板的头文件

头文件

描        述

<vector>

定义vector序列模板,这是一个大小能够从新设置的数组类型,比普通数组更安全、更灵活

<list>

定义list序列模板,这是一个序列的链表,经常在任意位置插入和删除元素

<deque>

定义deque序列模板,支持在开始和结尾的高效插入和删除操做

<queue>

为队列(先进先出)数据结构定义序列适配器queue和priority_queue

<stack>

为堆栈(后进先出)数据结构定义序列适配器stack

<map>

map是一个关联容器类型,容许根据键值是惟一的,且按照升序存储。multimap相似于map,但键不是惟一的。

<set>

set是一个关联容器类型,用于以升序方式存储惟一值。multiset相似于set,可是值没必要是惟一的。

<bitset>

为固定长度的位序列定义bitset模板,它能够看做固定长度的紧凑型bool数组

C7. 支持迭代器的头文件

 

头文件

描        述

<iterator>

给迭代器提供定义和支持

C8. 有关算法的头文件

头文件

描        述

<algorithm>

提供一组基于算法的函数,包括置换、排序、合并和搜索

<cstdlib>

声明C标准库函数bsearch()和qsort(),进行搜索和排序

<ciso646>

容许在代码中使用and代替&&

C9. 有关数值操做的头文件

头文件

描        述

<complex>

支持复杂数值的定义和操做

<valarray>

支持数值矢量的操做

<numeric>

在数值序列上定义一组通常数学操做,例如accumulate和inner_product

<cmath>

这是C数学库,其中还附加了重载函数,以支持C++约定

<cstdlib>

提供的函数能够提取整数的绝对值,对整数进行取余数操做

C10. 有关本地化的头文件

头文件

描        述

<locale>

提供的本地化包括字符类别、排序序列以及货币和日期表示。

<clocale>

对本地化提供C样式支持

 

2.2.5名字空间的嵌套

在用户声明的名字空间中还能够继续嵌套其余的名字空间,经过这种分层次的名字空间的结构能够改善函数库的代码组织结构。具体代码以下:

Namespace myFirstSpace

{

Int myVar = 10;

Namespace mySecondSpace

{

   int dlVar = 314;

   Int myVar = 100;//它会隐藏外围名字空间声明的变量。

}

}

只要须要,名字空间的嵌套能够一直向下持续下去。在名字空间嵌套的时候,外围名字空间声明的变量可能会被里面嵌套的名字空间声明的同名变量隐藏。在使用嵌套名字空间成员的时候,有三种方式,具体状况以下:

//第一种形式:限定修饰名称形式

Int a = MyFirstSpace::mySecondSpace::dlVar;

//第二中形式:using声明的形式:

Using myFirstSpace::mySecondSpace::dlVar;

Int a= dlVar;

//第三中形式:using指示符形式:

Using namespace myFirstSpace::mySecondSpace;

Int a = dlVar;

 

2.2.6未命名名字空间

使用未命名的名字空间,能够定义文件做用域。具备文件做用域的名字空间只在定义它的文件中有效,在其余文件中访问不到该做用域。

未命名名字空间的定义格式以下:

----------------------------A.cpp--------------------------

Namespace

{

   Int a = 10;

   Void myFunction(int Para)

{

}

}

 

//使用未命名名字空间中的成员

Void main()

{

   myFunciton(a);//直接使用,不须要限定修饰。

}

    在使用未命名名字空间中的成员的时候,能够直接使用,不须要限定修饰。未命名名字空间中的成员只能在定义它的文件中使用,在其余文件中是没法访问的。

相关文章
相关标签/搜索