1. 函数模板
首先,我们定义一个函数模板,如下所示:
// returns 0 if the values are equal, 1 if v1 is larger, -1 if v1 is smaller template <typename T> int compare(const T &v1, const T &v2) { if(v1 < v2) return -1; if(v1 > v2) return 1; return 0; } (1)模板形参表解析:模板形参可以是表示类型的类型形参,也可以是表示常量表达式的非类型形参。
(2)实例化模板函数
解析:编译器能够确定用什么类型代替每个类型形参,以及用什么值代替每个非类型形参。推导出实际模板实参后,编译器使用实参代替相应的模板形参产生并编译该版本的函数。
(3)inline函数模板
template <typename T> inline T min(const T&, const T&)解析:需要说明的是inline放在模板形参后,返回类型前。在类内定义的函数默认为inline成员函数,而在类外定义的函数前面需加inline才是内联函数。
2. 类模板
首先,我们定义一个类模板,如下所示:
template <class Type> class Queue { public: Queue(); // 默认构造函数 Type& front(); // 返回队头元素的引用 const Type& front() const; void push(const Type&); // 在队尾增加一项 void pop(); // 从队头删除一项 bool empty() const; // 指出队列中是否有元素 private: // ... } 当我们使用类模板时,必须显示指定实参,比如Queue< vector<double> > qc; 那么Queue中Type的实际类型为vector<double>。说明:像通常的函数或类一样,我们可以仅对函数模板或类模板进行声明操作而不进行定义操作。
3. 模板特殊化
解析:模板特殊化定义:template <> class class_name <type>。
(1)在类名称后面必须将使用的具体数据类型写在尖括号<>中,比如template <> class pair <int> {}。
(2)重新定义类的所有成员(成员变量和成员函数)的特殊化实现。
4. 模板定义常用方式
解析:
(1)template <class T> // 一个class参数 (2)template <class T, class U> // 两个class参数 (3)template <class T, int N> // 一个class和一个整数 (4)template <class T = char> // 有一个默认值 (5)template <int Tfunc (int)> // 参数为一个函数
说明:一般情况,C++模板的声明和定义要放在同一个文件中。
5. 指针函数与函数指针
解析:
(1)指针函数本质是函数,该函数返回某一类型指针。函数原型:类型标识符* 函数名(参数表)。比如:int *f(x,y);
(2)函数指针本质是指针,即指向函数的指针变量。函数原型:类型标识符 (*函数名)(参数表)。比如:int (*f)(int x);
6. volatile
解析:volatile关键字确保本条指令不会因编译器的优化而省略,且要求优化器在用到这个变量时必须每次都小心地重新读取这个变量的值,而不是使用保存在寄存器里的备份。[2]
7. 条件编译
解析:当满足某条件时对一组语句进行编译,而当条件不满足时则编译另一组语句。常用的条件编译指令包括#if,#ifdef,#ifndef,#else,#elif,#endif等。
8. int sprintf( char *buffer, const char *format [, argument] ... );
解析:sprintf打印到字符串中,而printf打印到命令行中。比如sprintf(s, "%d", 123); // 产生字符串"123"。sprintf_s()是sprintf()的安全版本,通过指定缓冲区长度来避免sprintf()存在的溢出风险。
9. int fprintf( FILE *stream, const char *format, [ argument ]...)
解析:fprintf位于头文件<stdio.h>中,其作用是格式化输出到一个流/文件中;函数原型为int fprintf( FILE *stream, const char *format, [ argument ]...),fprintf()函数根据指定的格式(format)向输出流(stream)写入数据(argument)。比如printf(stream, "%d\n", i);
10. C++中的RTTI机制
解析:
RTTI(Runtime Type Information)即运行时类型信息,头文件是#include <typeinfo>。如下所示:
(1)typeid(datatype)的返回值类型是type_info类。
(2)typeid(datatype).name()返回当前变量的数据类型(一般数据类型,结构体或类等)。比如,int s; typeid(s).name()。
(3)可以使用type_info类中重载的==和!=运算符比较两个对象的类型是否相等。比如,typeid(*a) == typeid(A)。
11. C++ 标准库异常类
解析:
exception类定义在头文件#include <exception>中,它的两个主要派生类为logic_error和runtime_error,这两个类定义在头文件#include <stdexcept>中(这个头文件包含在#include <exception>中)。logic_error类用于描述程序中出现的逻辑错误,比如传递无效参数等。runtime_error指那些无法预料的事件所造成的错误,比如硬件故障或内存耗尽等。
(1)从logic_error派生的异常类
domain_error:报告违反了前置条件。invalid_argument:表明抛出这个异常的函数接收到了一个无效的参数。length_error:表明程序试图产生一个长度大于等于npos的对象(npos是环境尺寸大小的最大可能值,通常为std::size_t)。out_of_range:报告一个参数越界错误。bad_cast:抛出这个异常的原因是在运行时类型识别中发现程序执行了一个无效的动态类型转换(dynamic_cast)表达式。bad_typeid:当表达式typeid(*p)中的参数p是一个空指针时抛出这个异常。(2)从runtime_error派生的异常类
range_error:报告违反了后置条件。overflow_error:报告了一个算术溢出错误。bad_alloc:报告一个失败的存储分配。说明:size_t(#include <cstddef>)是一个与机器相关的unsigned类型,其大小足以保证存储内存中对象的大小。
12. auto_ptr
解析:std::auto_ptr类定义在头文件#include <memory>中,用来实现动态分配对象以及当对象不再需要时自动执行清理。如下所示:
#include <iostream> #include <memory> #include <cstddef> using namespace std; class TraceHeap { int i; // private public: static void* operator new (size_t siz){ void* p = ::operator new(siz); cout << "allocating traceheap object on the heap at address " << p << endl; return p; } static void operator delete (void* p) { cout << "deleting traceheap object at address " << p << endl; ::operator delete(p); } TraceHeap(int i) : i(i) {} int getVal() const { return i; } }; int main() { auto_ptr<TraceHeap> pMyObject(new TraceHeap(5)); cout << pMyObject->getVal() << endl; return 0; } ///:~说明:尽管程序没有显式删除原始指针,但是在栈反解的时候,pMyObject对象的析构函数会删除该原始指针。
13. static成员函数
解析:
(1)static成员函数是类的组成部分,而不是任何对象的组成部分。
(2)static成员函数没有this指针。
(3)static成员函数不能声明为const。
说明:C++没有原始基类的概念。
14. 预定义的宏名称
解析:
(1)__LINE__:整数值,表示当前正在编译的行在源文件中的行数。
(2)__FILE__:字符串,表示被编译的源文件的文件名。
(3)__DATE__:一个格式为"Mmm dd yyyy"的字符串,存储编译开始的日期。
(4)__TIME__:一个格式为"hh:mm:ss"的字符串,存储编译开始的时间。
(5)__cplusplus:整数值,所有C++编译器都定义了这个常量为某个值。如果这个编译器是完全遵守C++标准的,它的值应该等于或大于199711L,具体值取决于它遵守的是哪个版本的标准。
说明:C++中常用的预处理指令有#define,#undef,#ifdef,#ifndef,#if,#endif,#else,#elif,#line,#error,#include,#pragma等。
15. 高级类型转换 [4]
解析:ANSI-C++标准定义了4种类型转换操作符reinterpret_cast <new_type> (expression);dynamic_cast <new_type> (expression);static_cast <new_type> (expression);const_cast <new_type> (expression)。其中,new_type是要转换成的目标类型,expression是要被转换的内容。如下所示:
(1)reinterpret_cast:可以将一个指针转换为任意其它类型的指针。它也可以用来将一个指针转换为一个整型,或反之亦然。
(2)static_cast:执行所有能够隐含执行的类型转换,以及它们的反向操作(即使这种方向操作是不允许隐含执行的)。
(3)dynamic_cast:用来进行任何可以隐含进行的转换操作以及它们被用于多态类情况下的方向操作。
(4)const_cast:这种类型转换对常量const进行设置或取消操作。
16. 文件的输入输出
解析:C++中支持文件的输入输出类:ofstream写操作(输出)的文件类(继承ostream类);ifstream读操作(输入)的文件类(继承istream类);fstream可同时读写操作的文件类(继承iostream派)。
(1)打开文件模式
ios::in:为输入(读)而打开文件。ios::out:为输出(写)而打开文件。ios::ate:初始位置为文件尾。ios::app:所有输出附加在文件末尾。ios::trunc:如果文件已存在则先删除该文件。ios::binary:二进制方式。 说明:ofstream,ifstream和fstream类的成员函数open包含默认打开文件的方式,分别为ios::out | ios::trunc,ios::in,os::in | ios::out。 (2)eof和getline函数 eof是ifstream从类ios中继承过来的,当到达文件末尾时返回true。getline函数的作用是从输入流中读取一行字符,语法istream& getline (istream& is, string& str, char delim)。 (3)状态标志符 bad():如果在读写过程中出错,那么返回true。fail():如果在读写过程中出错,或格式错误,那么返回true。eof():如果读文件到达文件末尾,那么返回true。good():如果没有以上错误,那么返回true。clear():重置以上成员函数所检查的状态标志。 (4)获得和设置流指针 ifstream:有一个被称为get pointer的指针,指向下一个将被读取的元素。ofstream:有一个被称为put pointer的指针,指向写入下一个元素的位置。fstream:同时继承了get和put属性。 说明:ofstream类,ifstream类和fstream类均在头文件#include <fstream>中。 17. struct与class 解析:struct继承class是public继承,而class继承struct是private继承。 18. SLAM 解析:SLAM(simultaneous localization and mapping)即时定位与地图构建。 19. 动态绑定和静态绑定 [5] 解析: (1)对象的静态类型:对象在声明时采用的类型,是在编译期确定的。 (2)对象的动态类型:目前所指对象的类型,是在运行期决定的。 (3)静态绑定:绑定的是对象的静态类型,某特性(比如函数)依赖于对象的静态类型,发生在编译期。 (4)动态绑定:绑定的是对象的动态类型,某特性(比如函数)依赖于对象的动态类型,发生在运行期。 说明:对象的动态类型可以改变,但是静态类型不能改变。只有虚函数使用的是动态绑定,其他的全部使用的是静态绑定(包括缺省参数)。 20. 文件位置指针 解析: istream提供了用于重新定位文件位置指针的成员函数seekg,ostream提供了用于重新定位文件位置指针的成员函数seekp。如下所示: (1)fileObject.seekg( n ); (2)fileObject.seekg( n, ios::cur ); (3)fileObject.seekg( n, ios::end ); (4)fileObject.seekg( 0, ios::end ); 说明:seekg和seekp的第一个参数通常是一个长整型,第二个参数用于指定查找方向,其中ios::beg表示从流的开头开始定位(默认),ios::cur表示从流的当前位置开始定位,ios::end表示从流的末尾开始定位。 21. C++标准异常 解析:C++标准异常定义在头文件#include <exception>中,如下所示: (1)std::exception:该异常是所有标准C++异常的父类。 (2)std::bad_alloc:该异常可以通过new抛出。 (3)std::bad_cast:该异常可以通过dynamic_cast抛出。 (4)std::bad_exception:这在处理C++程序中无法预期的异常时非常有用。 (5)std::bad_typeid:该异常可以通过typeid抛出。 (6)std::logic_error:理论上可以通过读取代码来检测到的异常。 (7)std::domain_error:当使用了一个无效的数学域时,会抛出该异常。 (8)std::invalid_argument:当使用了无效的参数时,会抛出该异常。 (9)std::length_error:当创建了太长的std::string时,会抛出该异常。 (10)std::out_of_range:该异常可以通过方法抛出,比如std::vector和std::bitset<>::operator[]()。 (11)std::runtime_error:理论上不可以通过读取代码来检测到的异常。 (12)std::overflow_error:当发生数学上溢时,会抛出该异常。 (13)std::range_error:当尝试存储超出范围的值时,会抛出该异常。 (14)std::underflow_error:当发生数学下溢时,会抛出该异常。 22. C++标准库 [6] 解析: (1)标准函数库:这个库是由通用的、独立的、不属于任何类的函数组成的。函数库继承自C语言。 输入/输出 I/O字符串和字符处理数学时间、日期和本地化动态分配宽字符函数其他 (2)面向对象类库:这个库是类及其相关函数的集合。 标准的 C++ I/O 类String 类数值类STL容器类STL算法STL函数对象STL迭代器STL分配器本地化库异常处理类杂项支持库 说明:C++标准库包含所有的C标准库,为了支持类型安全,做了一定的添加和修改。 23. C/ C++常用头文件 解析: (1)#include <deque>:STL双端队列容器。 (2)#include <exception>:异常处理类。 (3)#include <fstream>:文件输入/输出。 (4)#include <functional>:STL定义运算函数(代替运算符)。 (5)#include <limits>:定义各种数据类型最值常量。 (6)#include <list>:STL线性列表容器。 (7)#include <map>:STL映射容器。 (8)#include <iomanip>:参数化输入/输出。 (9)#include <ios>:基本输入/输出支持。 (10)#include <sstream>:基于字符串的流。 (11)#include <stack>:STL堆栈容器。 (12)#include <algorithm>:STL通用算法。 (13)#include <bitset>:STL位集容器。 (14)#include <cctype>:字符处理。 (15)#include <stdexcept>:标准异常类。 (16)#include <streambuf>:底层输入/输出支持。 (17)#include <string>:字符串类。 (18)#include <utility>:STL通用模板类。 (19)#include <vector>:STL动态数组容器。 (20)#include <iosfwd>:输入/输出系统使用的前置声明。 (21)#include <cerrno>:定义错误码。 (22)#include <clocale>:定义本地化函数。 (23)#include <cmath>:定义数学函数。 (24)#include <complex>:复数类。 (25)#include <cstdio>:定义输入/输出函数。 (26)#include <cstdlib>:定义杂项函数及内存分配函数。 (27)#include <cstring>:字符串处理。 (28)#include <ctime>:定义关于时间的函数。 (29)#include <iostream>:数据流输入/输出。 (30)#include <istream>:基本输入流。 (31)#include <ostream>:基本输出流。 (32)#include <queue>:STL队列容器。 (33)#include <set>:STL集合容器。 (34)#include <cwchar>:宽字符处理及输入/输出。 (35)#include <cwctype>:宽字符分类。 (36)#include <complex.h>:复数处理。 (37)#include <fenv.h>:浮点环境。 (38)#include <inttypes.h>:整数格式转换。 (39)#include <stdbool.h>:布尔环境。 (40)#include <stdint.h>:整型环境。 (41)#include <tgmath.h>:通用类型数学宏。 参考文献:[1] C++ Primer(第4版)
[2] volatile:http://baike.baidu.com/link?url=VEBsQt5II-QxbLx-CrpazjHbyWt5tVMflp_EaCSK_n50c5KABprxEgfnq1mdn_Krjzeq_cpybReD4H2epmPDya
[3] 条件编译:http://baike.baidu.com/link?url=x92_9-h5i4tA01RIUg-0aqO6M1n77uv2u7zpA1Mcp9TTVlTYMm6lQGq4EE3Mvyf25fapXG00KJQysT1mAADqxq
[4] 类型转换高级:http://www.prglab.com/cms/pages/c-tutorial/advanced-concepts/class-type-casting.php
[5] 深入理解 C++ 的动态绑定和静态绑定:http://blog.csdn.net/chgaowei/article/details/6427731
[6] C++标准库:http://www.runoob.com/cplusplus/cpp-standard-library.html
