C++primer学习笔记_第1页
C++primer学习笔记_第2页
C++primer学习笔记_第3页
C++primer学习笔记_第4页
C++primer学习笔记_第5页
已阅读5页,还剩37页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、C+ Primer第一章 开始1、在 C+中 动作被称为表达式 expression 以分号结尾的表达式被称作语句 statement,C+中最小的程序单元是语句。2、函数由四部分组成 返回类型 函数名 参数表 以及函数体 前三部分合起来称为函数原型 function prototype。3、错误类型:语义错误,语法错误。4、头文件通过 include 预处理器指示符 preprocessor include directive 而成为我们程序的一部分 预处理器指示符用 # 号标识。由于嵌套包含文件的原因 一个头文件可能,会被多次包含在一个源文件中 条件指示符可防止这种头文件的重复处理 。例如

2、:#ifndef BOOKSTORE_H#define BOOKSTORE_H/* Bookstore.h 的内容 */#endif5、assert()是 C 语台标准库中提供的一个通用预处理器宏 在代码中常利用 assert()来判断一个必需的前提条件 以便程序能够正确执行。6、C+的输入/输出功能由输入/输出流 iostream 库提供 输入/输出流库是 C+中一个面向对象的类层次结构 也是标准库的一部分。7、iostream 库也支持文件的输入和输出,必须包含:#include <fstream>。为了打开一个输出文件 我们必须声明一个 ofstream 类型的对象:ofst

3、ream outfile( "name-of-file" );为了测试是否已经成功地打开了一个文件 我们可以写出这样的代码if ( ! outfile ) / 如文件不能打开值为 falsecerr << "Sorry! We were unable to open the file!n"类似地 为了打开一个文件供输入 我们必须声明一个 ifstream 类型的对象ifstream infile( "name of file" );if ( ! infile )cerr << "Sorry! We w

4、ere unable to open the file!n"第二章 C+浏览。 1、为什么内置数组类型不支持数组之间的赋值 支持这种操作需要什么信息?答:数组具有退化性,数组在这里退化为指针而不表示整个数组。而数组退化得到的指针是常量,因此数组无法作为operator=的左操作数;组类型(元素类型和长度)完全相同或者元素类型相同但左操作数的长度大于等于右操作数的长度。 2、你认为作为一等公民的数组应该支持什么操作?数组初始化、数组比较、数组赋值、数组大小查询、数组索引范围检验等3、构造函数,析构函数的作用。类的构造函数主要用来初始化类对象的数据成员 析构函数主要负责释放类对象在生命期

5、内申请到的所有资源。4、异常设计(catch捕捉的类型要与throw的类型一样)。5、名字空间的使用,它独立于全局名字空间 我们可以在里面放一些希望声明在函数或类之外的实体 名字空间井不改变其中的声明的意义 只是改变了它们的可视性。第三章 C+数据类型1、文字常量:“F”,“f”,“L”,“l”后缀只能用在十进制形式中。文字常量是不可寻址的。2、变量:变量为我们提供了一个有名字的内存存储区,因此可寻址,同时可以通过程序对其进行读 写和处理。注意命名规则(如不能以数字开头、关键字)。3、指针类型:指针持有另一个对象的地址,使我们能够间接地操作这个对象。指针都是4个字节。注意指针的使用。4、字符串

6、类型:学会所有字符串处理函数的使用。特别注意字符串指针,字符指针的操作。5、const限定修饰符:被const定义的变量必须初始化,因为没法改变。Const对象的地址只能赋值给const类型的指针。6、引用类型:引用必须被初始化,因为一旦引用被定义,也就不能修改。另外注意const类型的引用的不同。如:const int ival = 1024;/ 错误: 要求一个 const 引用int *&pi_ref = &ival;const int ival = 1024;/ 仍然错误const int *&pi_ref = &ival;如果我们从右向左读这个定义会发

7、现 pi_ref 是一个指向定义为 const 的 int 型对象的指针,引用不是指向一个常量 而是指向一个非常量指针 指针指向一个 const 对象。正确的定义如下:const int ival = 1024;/ ok: 这是可以被编译器接受的const int *const &pi_ref = &ival;7、bool类型:它不能被声明为 signed unsigned short 或 long; 当表达式需要一个算术值时 布尔对象(如 found)和布尔文字都被隐式地提升成 int(正如下面的例子) false 变成 0 而 true 变成 1。8、枚举类型:枚举类型用关

8、键字 enum 加上一个自选的枚举类型名来定义 类型名后面跟一个用花括号括起来的枚举成员列表 枚举成员之间用逗号分开 在缺省情况下 第一个枚举成员被赋以值 0 后面的每个枚举成员依次比前面的大 1。如:/ point2d = 2, point2w = 3, point3d = 3, point3w = 4enum Points point2d = 2, point2w, point3d = 3, point3w ;9、 数组类型:一个数组不能被另外一个数组初始化 也不能被赋值给另外一个数组 而且 C+不允许声明一个引用数组(即由引用组成的数组);数组维数的指定必须是常量表达式。10、 vect

9、or容器类:与数组不同,可以进行赋值。具有两种不同形式(数组形式和STL形式,区别在与是否固定大小)。典型的对vector容器的操作是采用迭代器。同时初始化时特别注意。如:Vector <int> arr = 1,2,3;/错误,不能以该中方式,进行赋值。11、复数类型: 复数 complex number 类是标准库的一部分,必须包含其相关的头文件#include <complex>。每个复数都有两部分 实数部分和虚数部分。复数支持加 减 乘 除和相等比较。12、typedef名字:使用例子如:typedef vector<int> vec_int;vec

10、_int vec1( 10 );作用:降低声明复杂度。13、valotile修饰符:禁止优化的作用。14、pair类型:它可以在单个对象内部把相同类型或不同类型的两个值关联起来 为了使用 pair 类必须包含下面的头文件:#include <utility>例如:pair< string, string > author( "James", "Joyce" );15、类类型:就是自定义的类类型。第四章 表达式1、 什么是表达式:表达式由一个或多个操作数 operand 构成 最简单的表达式由一个文字常量或一个对象构成。注意操作符一

11、元、二元、多元。2、 算术操作符:%,/等。注意上溢、下溢。3、 等于、关系和逻辑操作符:操作结果都是bool。4、 赋值操作符:=。注意左值与右值的区别。5、 递增递减:+,-。注意前自增自减与后自增自减的区别。6、 复数操作:算术数据类型不能直接被一个复数类对象初始化或赋值 例如 下列代码将导致编译错误/ 错误: 从复数到内置算术数据类型之间/ 并没有隐式转换支持double dval = complex_obj;实部虚部的读取:double re = complex_obj.real();double im = complex_obj.imag();或者用等价的非成员语法/ 等价于上面的

12、成员语法double re = real( complex_obj );double im = imag( complex_obj );*:同时支持直接输出。7、 条件操作符:if()。8、 sizeof操作符:siseof 操作符的作用是返回一个对象或类型名的字节长度。同时sizeof是在编译时刻计算,所以是常量表达式。而且它有以下三种形式:sizeof (type name );sizeof ( object );sizeof object;9、 new和delete表达式:new和delete成对出现,且new的对象是在堆中。另外还有一个特点就是new出来的对象都是未命名的。10、逗号操

13、作符:逗号表达式的结果是最右边表达式的值。11、位操作符:12、bitset操作:13、优先级:主要是符号也运算优先级。14、类型转换:一、隐式转换:如:int num = 3.14;二、算术转换:如:int+float+double = double;三、显示转换:如:static_cast四、旧式强制转换:如:int ival = (int) 3.14159;15、栈类实例:就是把前面的知识用在一个简单类里面进行实现,验证。第五章 语句1、 简单语句和复合语句:简单语句:如:int num =5。复合语句:一对花括号括起来的语句。2、声明语句:如:int ivar;注意声明的局部性。3、i

14、f语句:按条件执行。4、switch语句:选择语句。5、for语句:循环语句。6、while语句:循环语句。7、do while 语句:循环语句。8、break语句:结束循环。9、continue语句:结束本次循环。10、goto语句:跳转语句,可以实现循环。如: A: goto A;第六章 抽象容器类型1、 我们的文本查询系统:分析该系统的需要。2、 Vector还是list:vector内存连续,随机访问效率高;list内存不连续,随机添加删除效率高。两者相比,数据越大越复杂,vector效率就越低,list就越高。下面是选择顺序容器类型的一些准则:(1)如果我们需要随机访问一个容器 则

15、vector 要比 list 好得多(2)如果我们已知要存储元素的个数 则 vector 又是一个比 list 好的选择(3)如果我们需要的不只是在容器两端插入和删除元素则 list 显然要比 vector 好3、 Vector怎样自己增长:当vector被占满后,继续插入元素时候,就会分配二倍与当前容量大小的内存。数据越大越复杂,vector效率就越低-如:4、 定义一个顺序容器:能够定义的容器的类型有三个限制:元素类型必须支持等于操作符。元素类型必须支持小于操作符 前面讨论的所有关系操作符都用这两个操作符来实现。元素类型必须支持一个缺省值。5、 迭代器:迭代器 iterator 提供了一种

16、一般化的方法 对顺序或关联容器类型中的每个元素进行连续访问。每种容器类型都提供一个 begin()和一个 end()成员函数*:begin()返回一个 iterator 它指向容器的第一个元素*:end()返回一个 iterator 它指向容器的末元素的下一个位置6、 顺序容器操作:插入,删除等操作。如:push_back(),pop_back(),insert(),erase(),swap();互换:如果两个容器的长度不同 则容器的长度就被重新设置 且等于被拷贝容器的长度7、 存储文本行:一次读取一行,getline,然后进行单词拆分。8、 找到一个子串: string name( &quo

17、t;AnnaBelle" );int pos = name.find( "Anna" );if ( pos = string:npos )cout << "Anna not found!n"else cout << "Anna found at pos: " << pos << endl;pos = name.find_first_of( numerics, pos )-à说明:在name字符串里面查找出现numberics里面任何一个字符首次出现的位置,从name的

18、pos位置开始查找。没有则返回-1.pos = name.find_last_of( numerics, pos )-à说明:在name字符串里面查找出现numberics里面任何一个字符最后一次出现的位置,从name的pos位置开始查找。没有则返回-1.9、 处理标点符号:处理标点符号跟处理空格类似。10、任意其他格式的字符串:string字符串的compare和replace等函数的使用问题。11、其他string操作:erase,insert,find,append,assign等操作。12、生成文本位置map:map的定义如:map<string, int> wo

19、rd_count; 访问map的int值方法:int age=word_count“xiafusen”;但是如果map中不存在”xiafusen”这样的键值,就会发生新插入一个一”xiafsen”为键值,0为age的一对map值。为了避免这样的事情发生,则必须要先知道你面是否存在键值”xiafusen” 方法判断word_count.count( "xiafusen" )返回值;或则使用find函数。如:int count = 0;map<string,int>:iterator it = word_count.find( "wrinkles"

20、; );if ( it != word_count.end() )count = (*it).second; 对map的迭代就像对vector的迭代是一样的。Begin、end等。访问第一个元素为:对象.frist,访问第二个元素为:对象.second。13、 创建单词排序集:注意set与vector的区别。Set中不存在相同的元素存在。14、 完整的程序:程序的实现代码。15、 mutilmap,mutilset:map 和 set 只能包含每个键的单个实例 而 multiset 和 multimap 允许要被存储的键出现多次。因此不支持下标操作。16、栈:先进后出17、对列和优先级队列:先

21、进先出。标准库提供两种队列->FIFO队列和优先级队列。18、回顾istack类:解除某些限制,重写某些函数。第七章 函数1、概述:函数返回值,函数参数,函数体,函数名。函数的声明描述了函数的接口,如:参数列表,返回值等。2、函数原型: (1)函数返回值:函数返回类型可以是预定义类型;如 int 或 double。 复合类型;如 int&或 double*280。用户定义类型;如枚举 类或 void 后者意指函数不返回值。 (2)函数参数表:不能省略,逗号隔开。 (3)参数类型检查:每个函数调用的实参在编译链接是都会经过参数类型检查。3、参数传递:所有的函数都使用在程序运行栈 r

22、un-time stack 中分配的存储区 该存储区一直保持与该函数相关联 直到函数结束为止。(1)引用参数:第一种用法:像 swap()的情况 它必须将一个参数改变成指针来允许改变实参的值时就比较合适。第二种普遍用法是向主调函数返回额外的结果 。第三种用法是向函数传递大型类对象,避免额外的负责带来的开销。(2)应用参数和指针参数的关系:应用必须被初始化指向一个对象,而指针并不必须要初始化。(3)数组参数:永远不可能按值传递,另外声明时与数组长度无关。(4)抽象容器类参数:如:void show(vector<string> vstr);(5)缺省实参:char *screenIn

23、it( int height = 24, int width = 80,char background = ' ' ); char *cursor;/ 等价于 screenInit(24,80, ' ')cursor = screenInit();(6)省略号:典型的函数printf。声明如:int printf( const char* . );省略号有下列两种形式void foo( parm_list, . );void foo( . );4、返回一个值:由return返回的内容。这条语句结束整个函数。另外可以通过return返回结果。一个具有返回类型的函数

24、必须具有返回值,要不然编译要出现错误。另外如果实际的返回值如果跟返回值类型不同,则进行隐式转换,如果不能通过隐式转换,那么就会出现编译错误。同时你会发现如果返回的对象比较大的时候返回引用,指针比返回值高效许多。5、递归:直接或间接的调用自己的函数被称为递归函数。因此必须有个结束条件。如:int rgcd( int v1, int v2 )if ( v2 != 0 )return rgcd( v2, v1%v2 );return v1;6、inline函数:若一个函数被指定为 inline 函数 则它将在程序中每个调用点上被 内联地 展开 例如int minVal2 = min( i, j );

25、在编译时被展开为:int minVal2 = i < j << i : j;注意: inline 指示对编译器来说只是一个建议 编译器可以选择忽略该建议 因为把一个函数声明为 inline 函数 并不见得真的适合在调用点上展开。因此inline只是用于那些较小,只有几行代码,经常被调用的函数。7、链接提示符,extern “C”:注意:不能放在函数体内。程序员用链接指示符 linkage directive 告诉编译器 该函数是用其他的程序设计语言编写的 链接指示符有两种形式 既可以是单一语句 single statement 形式 也可以是复合语句 compound sta

26、tement 形式/ 单一语句形式的链接指示符extern "C" void exit(int);/ 复合语句形式的链接指示符extern "C" int printf( const char* . );int scanf( const char* . );/ 复合语句形式的链接指示符extern "C" #include <cmath>8、main处理命令行参数:int main( int argc, char *argv ) . argc 包含命令行选项的个数 argv 包含 aygc 个 C 风格字符串。9、专项函数

27、的指针:(1)指向函数指针的类型:定义:如 int myadd(int x,int y);-àint (*pf)(int x ,int y);省略号是函数类型的一部分 如果两个函数具有相同的参数表 但是一个函数在参数表末尾有省略号 则它们被视为不同的函数类型(2)初始化和赋值:初始化:如 int myadd(int x,int y);-àint (*pf)(int x ,int y)=&myadd;赋值:pf = &myadd;(3)调用:调用:如 int x=5,y=6; pf(x,y);或(*pf)(x,y);(4)函数指针的数组:如: int (*pf

28、10)(int x ,int y);(5)参数和返回类型:函数不能声明一个返回类型为函数类型,如果是就会发生编译错误。(6)指向extern “C”的函数指针:指针 pf 指向一个 C 函数如:extern "C" void (*pf)(int); 当用 pf 调用一个函数时 被调用的函数是一个 C 函数extern "C" void exit(int); 注意指向 C 函数的指针与指向 C+函数的指针类型是不同的。第八章 域和生命周期1、 域:C+支持三种形式的域:局部域(函数空间内,变量的声明周期可以体现这一点),名字空间域(namespace,如:

29、using namespace std)和类域。*:注意习题,比较刁钻。2、全局对象和函数:全局域里面的对象、函数被称为全局对象,全局函数。(1)声明和定义:如:int x;/全局对象声明,若对象未初次化,则默认为0。 int add(int& x,int& y);/全局函数声明void mian()重点:注意extern的使用来实现一个全局变量在多个文档中被使用。(2)不同文件之间声明的匹配:注意要类型什么都一样。(3)谈谈头文件:一下是定义头文件几个需要注意的地方:头文件提供的声明逻辑上应该属于一个组;头文件不应该含有非 inline 函数或对象的定义;3、局部对象:有三种

30、局部对象: 1.自动对象2.寄存器对象3.局部静态变量(1)自动对象:自动对象的地址不应该被作为函数的返回值,因为函数一旦结束,改地址就指向一个无效地地址。当一个自动变量的地址被存储在一个生命期长于它的指针时 该指针被称为空悬指针。(2)寄存器自动对象:如:for ( register int ix = 0; ix < sz; +ix )/.如果所选择的变量被频繁使用 则寄存器变量可以提高函数的执行速度关键字 register 对编译器来说只是一个建议 有些编译器可能忽略该建议。(3)静态局部对象:静态局部对象在程序执行到该对象的声明处时被首次初始化;例如 下面是 gcd()的一个版本

31、它占用一个静态局部对象来跟踪递归的深度#include <iostream>int traceGcd( int v1, int v2 )static int depth = 1;cout << "depth #" << depth+ << endl;if ( v2 = 0 ) depth = 1;return v1;return traceGcd( v2, v1%v2 );另外未经过初始化的对象,默认值为0,自动对象则为随机的。4、动态分配的对象:动态分配的对象允许程序员完全控制它的分配与释放。(1)单个对象的动态分配与释放:

32、如:new int;new int(5);int *p = new int;int *p = new int(5);delete p;(2)auto_ptr:必须包含头文件#include<memeory>定义有下列三种形式:auto_ptr< type_pointed_to > identifier( ptr_allocated_by_new );auto_ptr< type_pointed_to > identifier( auto_ptr_of_same_type );auto_ptr< type_pointed_to > identifi

33、er;注意:不能让auto_ptr指向不是new出来的对象;不能让两个auto_ptr指向同一个地方。(3)数组的动态分配与释放:如:为避免动态分配数组的内存管理带来的问题 一般建议使用标准库 vector list 或 string容器类型 这些类型都会自动管理内存分配。(4)常量对象的动态分配与释放:注意必须初始化,以及指针必须为从const类型。(5)定位new表达式:new 表达式的第三种形式可以允许程序员要求将对象创建 在已经被分配好的内存中;自己没有看懂什么意思。5、名字空间定义:(1)名字空间定义:如:注意:名字空间定义不一定是连续的。(2)域操作符:就是 :在用到名字空间的时候

34、,会使用域操作符(:)实现函数,对象等的访问。(3)嵌套名字空间:如:访问的方法:在嵌套名字空间 MatrixLib 中声明的类的名字是cplusplus_primer:MatrixLib:matrix函数的名字是cplusplus_primer:MatrixLib:inverse(4 名字空间成员定义:名字空间成员可以被定义在名字空间定义之外,只有当一个名字空间成员在名字空间定义中已经被声明过 它才能在该名字空间定义之外被定义。(5)ODR和名字空间成员:名字空间的对象、函数只做声明,在其他文件中实现定义。(6)未命名的名字空间: 如:namespace/*、*/目的:局部与某文件中,在其他

35、文件中不可见。就可以避免名字冲突。6、使用名字空间成员:(1)名字空间别名:例如 长名字空间名如namespace International_Business_Machines /* . */ 可以与一个较短的同义词相关联 如下namespace IBM = International_Business_Machines;那么:International_Business_Machine:show()-àIBM:show();(2)using声明:如:using namespace std;在后面使用std空间类的对象,函数就可以直接使用,而不需要带名字空间作为说明了。(3) us

36、ing指示符:using 指示符以关键字 using 开头 后面是关键字 namespace 然后是名字空间名。(4) 标准名字空间std:里面包含<iostream>,<vector>等。第九章 重载函数 1、重载函数声明:函数重载 function overloading 允许多个函数共享同一个函数名 但是针对不同参数类型提供共同的操作。(1)为什么要重载一个函数名:实现多态。(2)怎样重载一个函数名:可以为两个或多个函数提供相同的名字 只要它们的每个参数表惟一就行,或者是参数的个数不同 或者是参数类型不同。(3)何时不重载一个函数名:如果不同的函数名所提供的信息可

37、使程序更易于理解的话 则再用重载函数就没有什么好处了。(4)重载与域:重载函数集合中的全部函数都应在同一个域中声明 例如 一个声明为局部的函数将隐藏而不是重载一个全局域中声明的函数(5)extern “c”和重载函数:链接指示符只能指定重载函数集中的一个函数。(6)指向重载函数的指针:void ( *pf1 )( unsigned int ) = &ff;unsigned int部分决定pf1指向那个函数。(7)类型安全连接:不适用于用链接指示符 extern "C"声明的函数。 2、重载解析的三个步骤:1 .确定函数调用考虑的重载函数的集合 确定函数调用中实参表的

38、属性2 .从重载函数集合中选择函数 该函数可以在 给出实参个数和类型 的情况下用调用中指定的实参进行调用。3 .选择与调用最匹配的函数3、参数类型转换:可能存在的转换如下:从左值到右值的转换;从数组到指针的转换;从函数到指针的转换;限定修饰转换;为一个函数调用选择最佳可行函数时 编译器会选择在实参的类型转换方面 最好 的一个函数 函数转换被划分等级如下 精确匹配比提升好 提升比标准转换好 标准转换比用户定义的转换好(1)精确匹配的细节:精确匹配最简单的例子是实参与函数参数类型精确匹配。 精确匹配中从左值到右值 从数组到指针以及从函数到指针的转换通常被称为左值转换 。(2)提升的细节:提升实际上

39、就是下列转换之一1.char unsigned char 或 short 型的实参被提升为 int 型 如果机器上 int 型的字长比short 整型的长 则 unsigned short 型的实参被提升到 int 型 否则 它被提升到unsigned int 型;2.float 型的实参被提升到 double 类型;3.枚举类型的实参被提升到下列第一个能够表示其所有枚举常量的类型 int 、unsigned int、 long 或 unsigned long;4.布尔型的实参被提升为 int 型;(3)标准转换的细节:(4)引用:重点:注意应用对转换的应用。4、函数重载解析细节:注意函数重载

40、解析过程的三个步骤。(1)候选函数:候选函数与被调用的函数具有同样的名字。(2)可行函数:可行函数是候选函数集合中的函数 它的参数表或者与调用中的实参数目相同 或者有更多的参数。可行函数是这样的函数 对于每个实参 都存在到函数参数表中相应的参数类型之间的转换。(3)最佳可行函数:最佳可行函数是具有与实参类型匹配最好的参数的可行函数,就是最后被执行的那个函数。(4)缺省实参:缺省实参可以使多个函数进入到可行函数集合中 ,可行函数是指可以用调用中指定的实参进行调用的函数 。可行函数可以有比函数调用实参表中的实参个数更多的参数,只要每个多出来的参数都有相应的缺省实参即可。如;第十章 函数模板1、函数

41、模板的定义:如:关键字 typename 也可以被用在模板参数表中 以指示一个模板参数是一个类型如同非模板函数一样, 函数模板也可以被声明为 inline 或 extern 应该把指示符放在模板参数表后面 而不是在关键字 template 前面。如: 重点:如果一个函数模板有一个以上的模板类型参数 则每个模板类型参数前面都必须有关键字 class 或 typename。2、函数模板实例化:函数模板指定了怎样根据一组或更多实际类型或值构造出独立的函数 ,这个构造过程被称为模板实例化。3、模板实参推演:当函数模板被调用时 对函数实参类型的检查决定了模板实参的类型和值 ,这个过程被称为模板实参推演。

42、如:template<class type>type Mysum(type x,type y);-à mysum(5,10);可以推演出type为int类型。4、显示模板实参: 如:template<class type>type Mysum(type x,type y);-à mysum<int>(5,10);显示指出type为int类型。 5、模板编译模式:C+支持两种方式的编译模式:1.包含模式 2.分离模式(1)包含编译模式:在包含编译模式下 我们在每个模板被实例化的文件中包含函数模板的定,并且往往把定义放在头文件中 像对内联函数

43、所做的那样。说白了就是在头文件声明的时候就直接定义了。(2)分离编译模式:头文件只负责声明,然后再.c文件中使用export说明并进行定义。(3)显示实例化声明:在显式实例化声明所在的文件中,函数模板的定义必须被给出。如:说明:对于给定的函数模板实例,显式实例化声明在一个程序中只能出现一次。 6、模板显示特化:函数模板 sum()被显式特化:template <class T1, class T2, class T3>T1 sum( T2 op1, T3 op2 );/ 显式特化声明/ 错误: T1 的模板实参不能被推演出来/ 它必须显式指定template<> dou

44、ble sum( float, float );/ ok: T1 的实参被显式指定/ T2 和 T3 可以从 float 推演出来template<> double sum<double>( float, float );/ ok: 所有实参都显式指定template<> int sum<int,char,char>( char , char ); 7、重载函数模板:如:8、考虑模板函数实例的重载解析:跟重载函数的解析过程基本一样。9、模板定义函数实例的重载解析:同上。10、名字空间和函数模板:同样,要先用using声明函数。11、函数模板示例:

45、 模板的定义和使用的例子程序,有必要读一读。第十一章 异常处理1、 抛出异常:异常 Exception 是程序可能检测到的,运行时刻不正常的情况;如被 0 除,数组越界访问或空闲存储内存耗尽等等。2、 Try块: try 块必须包围能够抛出异常的语句 ,try 块以关键字 try 开始,后面是花括号括起来的,语句序列 在 try 块之后是一组处理代码 被称为 catch 子句。3、 捕获异常:catch块进行异常处理。(1)异常对象:catch 子句的异常声明可以是一个类型声明或一个对象声明,这完全取决于throw抛出类型。(2)栈展开:在查找用来处理被抛出异常的 catch 子句时 因为异常

46、而退出复合语句和函数定义 这个过程被称作栈展开;随着栈的展开,尽管局部类对象的生命期是因为抛出异常而被结束 但是这些局部类对象的析构函数也会被调用。(3)重新抛出:在catch块中继续抛出异常。(4)catch-all处理代码:即使一个函数不能处理被抛出的异常。但是它也可能希望在带着异常退出之前执行一些动作。如:说明:这种 catch 子句有一个形式为( .) 的异常声明,这里的点被称为省略号,对任何类型的异常,都会进入这个 catch 子句。4、 异常规范:如:说明:声明时指明了异常规范,那么定义的时候也必须注明异常规范。额外:异常规范与函数指针:5、 异常与设计事项:虽然对于异常处理的支持

47、是被内置在语言中的,但并不是每个 C+程序都应该使用异常处理,因为抛出异常不像正常函数调用那样快,所以异常处理应该用在独立开发的不同程序部分之间,用于不正常情况的通信。第十二章 泛型算法1、 概述:每个泛型算法的实现都独立于单独的容器类型。2、 使用泛型算法:把一串泛型算法调用连接在一起的一个例子程序。3、 函数对象:函数对象三种来源:1.标准库预定义的一组算术 关系和逻辑函数对象;2.一组预定义的函数适配器,允许我们对预定义的函数对象,甚至于任何函数对象进行特殊化或者扩展;3.我们可以定义自己的函数对象 将其传递给泛型算法 或将它们传给函数适配器;(1)预定义函数对象:预定义函数对象被分成算

48、术、 关系和逻辑操作。(2)算术函数对象:预定义的算术函数对象支持加 减 乘 除 求余和取反。如:Plus,multiplies,divides,modulus,negate;(3)关系函数对象:预定义的关系函数对象支持等于 不等于 大于 大于等于 小于和小于等于;如:equal_to,not_equal_to,greater,greater_equal,less,less_equal;(4)逻辑函数对象:预定义的逻辑函数对象支持逻辑与,逻辑非,逻辑或;如:logical_and,logical_or,logical_not;(5)函数对象的函数适配器:被分为绑定器(binder)和取反器(n

49、egator);如:重点;(6)实现函数对象:实现小于等于功能。用类的方式实现。4、 回顾iterator:只是就举了一个iterator的使用例子。(1)插入iterator:back_inserter();front_inserter();inserter();如: 实现将ivec中所有内容插入到Vres中。 unique_copy( ivec.begin(), ivec.end(),back_inserter( vres );/后面插入unique_copy( ivec.begin(), ivec.end(),front_inserter( vres );前面插入unique_copy(

50、 ivec.begin(), ivec.end(),inserter( vres, vres.begin() );/指定位置插入。(2)反向iterator:反向 iterator 的遍历方式同前向 iterator 一样,不同的是对于前向 iterator +操作访问容器中的下一个元素,对于反向 iterator 它访问的是前面的元素。如:(3)iostream iterator:必须包含头文件->#include <iterator>;如:istream_iterator< int > input( cin );istream_iterator< int

51、 > end_of_stream;vector<int> vec;copy ( input, end_of_stream, inserter( vec, vec.begin() );sort( vec.begin(), vec.end(), greater<int>() );ostream_iterator< int > output( cout, " " );unique_copy( vec.begin(), vec.end(), output );(4)istream_iterator:如:(3)中的例子;(5)ostream_

52、iterator:如:(3)中的例子,另外定义有两种方式:(6)五中iterator:InputIterator,OutputIterator, ForwardIterator,BldirectionalIterator,和 RandomAccessIterator。介绍说明:P503。5、 泛型算法(1)查找算法:adjacent_find(), binary_search(), count(), count_if(), equal_range(),find(), find_end(), find_first_of(), find_if(), lower_bound(),upper_boun

53、d(), search(), search_n()(2)排序和通用整序算法:inplace_merge(), merge(), nth_element(), partial_sort(),partial_sort_copy(), partition(), random_shuffle(), reverse(),reverse_copy(), rotate(), rotate_copy(), sort(), stable_sort(),stable_partition();(3)删除和替换算法:copy(), copy_backwards(), iter_swap(), remove(), re

54、move_copy(),remove_if(), remove_copy_if(), replace(), replace_copy(),replace_if(), replace_copy_if(), swap(), swap_range(), unique(),unique_copy();(4)排列组合算法:next_permutation(), prev_permutation();(5)算法算法:accumulate(), partial_sum(), inner_product(), adjacent_difference();(6)生成和异变算法:fill(), fill_n(),

55、for_each(), generate(), generate_n(), transform();(7)关系算法:equal(), includes(), lexicographical_compare(), max(), max_element(),min(), min_element(), mismatch();(8)集合算法:set_union(), set_intersection(), set_difference(),set_symmetric_difference();(9)堆算法:make_heap(), pop_heap(), push_heap(), sort_heap(

56、);6、 何时不用泛型算法:如:map,set等关系容器不适合泛型算法,存储不连续。下面是list的容器的一些定制操作:list:merge() 用第二个有序的 list 合并一个有序 listlist:remove() 删除等于某个值的元素list:remove_if() 删除满足某个条件的元素list:reverse() 将 list 中元素反向排列list:sort() 排序 list 的元素list:splice() 把一个 list 的元素移到另一个 list 中list:unique() 删除某个元素的重复连续拷贝(1)list:merge():合并两个有序的list,合并后,il

57、ist2为空。(2)list:remove():为1的所有list实例全部删除。(3)list:remove_if():删除所有偶数。(4)list:reverse():反向。(5)list:sort():排序。(6)list:splice():搬移。(7)list:unique():使用方式一:使用unique之前,必须保证list序列有序。如:使用方式二:重点 如:第十三章 类1、类定义:类定义包含两部分:类头由关键字 class 及其后面的类名构成,类体由一对花括号包围起来 类定义后面必须接一个分号或一列声明(1)数据成员:可以是任意类型。注意,除了静态的数据成员,其他的任何类型的数据成员

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论