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