第3章 标注库类型
除第2章介绍的基本数据类型外,C++(www.cppentry.com)还定义了一个内容丰富的抽象数据类型标准库。其中最重要的标准库类型是string和vector,它们分别定义大小可变的字符串和集合。string和vector往往将迭代器当作伙伴类型(companion type),用于访问string中的字符,或者vector中的元素。这些标准库类型是作为语言组成部分的更基本的数据类型(如数组和指针)的抽象。
另一种标准库类型bitset,提供了一种抽象方法来操作位的集合。与整型值上的内置位操作符相比,bitset类类型提供了一种处理位的更方便的方式。
本章将介绍标准库中的vector,string和bitset类型。第4章将涉及到数组和指针,第5章将讲述内置位操作符。
第2章所涉及的类型都是低级数据类型:这些类型表示数值或字符的抽象,并根据其机器表示而定义。
除了这些在语言中定义的类型外,C++(www.cppentry.com)标准库还定义了许多抽象程度更高的抽象数据类型(abstract data types)。这些标准库类型之所以是高级的,是因为其中反映了更复杂的概念。说它们是抽象的,是因为程序员在使用时不需要关心它们是如何表示的。程序员只需知道这些抽象数据类型支持哪些操作就可以了。
两种最重要的标准库类型是string和vector。string类型支持长度可变的字符串,vector保存一系列指定类型的对象。说它们重要,是因为它们在C++(www.cppentry.com)定义的基本类型基础上作了一些改进。第4章还将学习类似于标准库中string和vector类型的语言级构造,但标准库的string和vector类型可能更灵活,且不易出错。
另一种标准库类型提供了更方便和合理有效的语言级的抽象机制,它就是bitset类。该类允许程序员把某个值当作位的集合来处理。与5.3节介绍的位操作符相比,bitset类提供操作位更直接的方法。
在继续探究标准库类型之前,我们先看一种简化对标准库中所定义名字的访问的机制。
3.1 命名空间using声明
幸运的是,C++(www.cppentry.com)提供了更简洁的方式来使用命名空间成员。本章将介绍一种最安全的机制:using声明。关于其他简化使用命名空间中名字的方法将在17.2节中介绍。
using声明允许程序员访问命名空间中的名字,而不需要加前缀namespace_name::。using声明的形式如下:
一旦使用了using声明,程序员就可以直接引用名字,而不需要引用该名字的命名空间:
#include <string> #include <iostream> // using declarations states our intent to use these names from the namespace std using std::cin; using std::string; int main() { string s; // ok: string is now a synonym for std::string cin >> s; // ok: cin is now a synonym for std::cin cout << s; // error: no using declaration; we must use full name std::cout << s; // ok: explicitly use cout from namepsace std } |
没有using声明,而直接使用命名空间中的名字的无限定符版本是错误的,尽管有些编译器也许无法检测出这种错误。
1. 每个名字需要一个using声明
一个using声明一次只能作用于一个命名空间成员。using声明允许程序员在程序中明确指定用到的命名空间中的名字,如果程序员希望使用std(或其他的命名空间)中的几个名字,则必须给出将要用到的每个名字的using声明。例如,利用using声明重新编写1.2.2节中的加法程序:
#include <iostream> // using declarations for names from the standard library using std::cin; using std::cout; using std::endl; int main() { cout << "Enter two numbers:" << endl; int v1, v2; cin >> v1 >> v2; cout << "The sum of " << v1 << " and " << v2 << " is " << v1 + v2 << endl; return 0; } |
对cin,cout和endl进行using声明,就意味着程序员可以省去前缀std::,直接使用命名空间中的名字,且使得编写的程序更易读。
从这里开始,假定本书所有例子中所用到的标准库里的名字都提供了using声明。这样,无论是在文档还是在代码实例中引用cin,我们都不再写为前缀形式std::cin。为了使代码实例简短,还会略去编译程序所必需的using声明。同样的,程序实例也会省略必要的#include指示。本书附录A中的表A-1列出了本书中用到的标准库名字的库名和相应的头文件。
在编译我们提供的实例程序前,读者一定要注意在程序中添加适当的#include和using声明。
2. 使用标准库类型的类定义
有一种情况下,程序员必须总是使用完全限定的标准库名字:在头文件中。理由是头文件的内容会被预处理器复制到程序员编制的程序中。当我们用#include包含文件时,就好像把头文件中的文本当作我们编写的文件的一部分了。如果在头文件中放置了using声明,就相当于在包含该头文件的每个程序中都放置了同一using声明,不论该程序是否需要using声明。
通常,头文件中只定义确实必要的东西。请养成这个好习惯。
习题
习题3.1 用适当的using声明,而不用std::前缀访问标准库中名字的方法,重新编写2.3节的程序,计算一给定数的给定次幂的结果。
在本章之前看到的程序,都是显式地从标准库中引用名字,名字都是取自std命名空间。例如,当程序员需要从标准输入读取数据时,就用std::cin,这些名字都用了::操作符,该操作符是作用域操作符(1.2.2节)。它的含义是右操作数的名字可以在左操作数的作用域中找到。因此,std::cin的意思是说程序员需要的名字cin被定义在命名空间std中。毫无疑问,通过这种符号引用标准库名字的方式是非常麻烦的。
【责任编辑:
董书 TEL:(010)68476606】