一、泛型编程:模板
1、函数模板
模板函数的定义可以放在接口文件中
1.比较同一类型数值大小
template <typename T, typename U, ... , typename C>
void functionName (U first , ... , Z last)
{
...
}
2.打印数组
template <typename T, int N>
void functionName (T (&array)[N])
{
...
}
3.显式类型确定
将不同类型的数值转换为同一类型
xxx <double>(A,B)
4.模板特化
字符串没有定义<,使用模板特化解决
template <typename T>
void functionName (const T& first , const T& second)
{
...
}
2、类模板
一般将声明放在.h文件中,将定义放在.cpp文件中
如果要独立编译,则要在template前加export
1.接口
template <typename T>
class Name
{
private:
T data;
public:
Name();
T get()const;
voic set(T data);
}
2.实现
template <typename T>
T name <T>::get()const
{
return data;
}
template <typename T>
void name <T>::set(T d)
{
data = d;
}
3.友元函数
模板类的声明可以包含友元函数
4.别名
有时可以使用关键字typedef为模板类定义别名
typedef stack <string,int> siStack;
5.继承
//模板类
template <typename T>
class First
{
...
}
//继承类
template <typename T>
class Second:public First <T>
{
...
}
二、异常处理
1.错误处理的传统方法
1.让运行环境中止程序
Nothing to do,当出现异常时让程序中止
2.请求运行时环境中止程序
在可能出现错误的地方打印,用assert宏中止程序抛出异常
3.错误检查
判断为会出现异常处,添加跳过语法,防止抛出异常
4.使用函数返回值进行错误检查
根据不同情况,返回不同值
2.异常处理方法
1.try-catch语句块
try
{
//可能产生异常的代码
}
catch
{
//处理异常的代码
}
2.三种模式
模式1
try-catch语句块完全包含在一个函数中(不常见)
int main()
{
try
{
...
throw xxx;
...
}
catch (type xxxx)
{
...
}
return 0;
}
模式2
由try中函数抛出异常(推荐)
int main()
{
try
{
...
xxxxx();
...
}
catch (type xxxx)
{
...
}
return 0;
}
type xxxxx (...)
{
...
throw xxx;
...
return xxxxxx;
}
异常处理方法的优点之一是我们可以设计能够抛出异常的函数。调用方负责处理异常
模式3
当被调用函数属于独立实体时(如类中的成员函数)时,出现异常,被调用函数无法继续执行剩余的代码,则需要这两个函数中都有try-catch语句块,catch子句重新抛出异常给主调函数,以便主调函数捕获该异常
3.throw语句
throw语句必须直接或者间接包含在try语句中
4.多条catch子句
一个函数可能抛出多种不同类型异常的情况,那么catch子句也要对应
try
{
throw A;
...
throw B;
}
catch (type1 obj1)
{
Handle xxxx;
}
catch (type2 obj2)
{
Handle xxxxx;
}
5.通用catch子句
catch子句只能捕获其参数类型的异常
6.异常传播
如果未在抛出异常的位置捕获和处理异常,则该异常将被自动传播到函数调用层次结构中的上一个函数
7.重新抛出异常
try
{
...
}
catch (type A)
...//某些处理工作
throw;//重新抛出异常给主调函数
3.异常规范
给别人用时,在函数头中添加表达式,以告诉用户如果在主调函数中捕捉异常
1.任何异常
函数可以抛出任何异常
2.预定义异常
如果函数的设计者和用户的不同,必须在函数头部定义函数抛出的异常
规范为函数声明后加上throw(xxx)
3.无异常
向用户声明此函数不引发异常
规范为函数声明后加上throw()
4.栈展开
1.程序内存
2.压入和弹出栈内存
3.栈展开的效果
由于函数返回或者抛出的异常而从占内存中弹出条目被称为栈展开。在栈展开期间,函数的参数和本地对象会通过调用其析构函数自动销毁(堆中可能会内存泄漏)
为了避免内存泄漏,必须使对象成为定义它们的函数的本地对象
5.类中的异常
1.构造函数中的异常
1.在栈内存中创建对象
1.在构造函数中不抛出异常
2.在构造函数中抛出异常
2.在堆内存中对象的部分创建
1.在构造函数中不抛出异常
2.在构造函数中抛出异常
3.使用智能指针进行内存管理
4.构造函数中try-catch语句块:function-try语句块
2.析构函数中的异常
必须避免在析构函数中引发异常
6.标准异常类
1.逻辑错误
逻辑错误与函数先决条件相关
要使用逻辑错误类,需要包含头文件
2.运行时错误
运行时错误与函数的后置条件相关
要使用运行时错误类,需要包含头文件
3.其他类
4.使用标准异常类
使用或者头文件中定义的标准异常类的对象