异常处理
1.throw表达式
throw runtime_error("Data must refer to same ISBN");
2.try块
while (cin >> item1 >> item2) {
try {
if (!item1.same_isbn(item2))
throw runtime_error("Data must refer to same ISBN");
} catch (runtime_error err) {
cout << err.what()
<< "\nTry Again? Enter y or n" << endl;
char c;
cin >> c;
if (cin && c == 'n')
break; // break out of the while loop
} }
3.标准库异常类
1.<exception> exception
2.<stdexcept>
exception 最常见的问题。
runtime_error 运行时错误:仅在运行时才能检测到问题
range_error 运行时错误:生成的结果超出了有意义的值域范围
overflow_error 运行时错误:计算上溢
underflow_error 运行时错误:计算下溢
logic_error 逻辑错误:可在运行前检测到问题
domain_error 逻辑错误:参数的结果值不存在
invalid_argument 逻辑错误:不合适的参数
length_error 逻辑错误:试图生成一个超出该类型最大长度的对象
out_of_range 逻辑错误:使用一个超出有效范围的值
3.<new>bad_alloc
4.<type_info> bad_cast
预处理进行调试
#ifndef NDEBUG
........
#endif
........
<cassert> assert()断言
-----------------------------
函数
返回值类型 函数名(形参列表){/函数体/}
int main (int argc, const char * argv[]){..}
函数必须指定返回类型
形参可以为空,但不能省略,可以不写或用void代替
传递的实参会检查类型,必须符合或经转换后可以符合
参数传递
每次调用函数时,都会重新创建该函数所有的形参,此时所传递的实参将会 初始化对应的形参。
形参的初始化与变量的初始化一样:如果形参具有非引用类型, 则复制实参的值,
如果形参为引用类型,则它只是实参的别名。
非引用形参:
普通的非引用类型的参数通过复制对应的实参实现初始化。当用实参副本初 始化形参时,
函数并没有访问调用所传递的实参本身,因此不会修改实参的值。
指针形参
函数的形参是指针,此时将复制实参指针,事实上被复制的指针只影响对指针的赋值。如果 函数形参是非 const 类型的指针,则函数可通过指针实现赋值,修改指针所指 向对象的值:
void reset(int *ip)
{
*ip = 0; // changes the value of the object to which ip points
ip = 0; // changes only the local value of ip; the argument is unchanged
}
调用 reset 后,实参依然保持原来的值,但它所指向的对象的值将变为 0:
如果保护指针指向的值,则形参需定义为指向 const 对象的指针:
void use_ptr(const int *p)
{
}
注:指针形参是指向 const 类型还是非 const 类型,将影响函数调用所使用的 实参。我们既可以用 int* 也可以用 const int* 类型的实参调用 use_ptr 函 数;但仅能将 int* 类型的实参传递给 reset 函数。这个差别来源于指针的初 始化规则。可以将指向 const 对象的指针初始化为指向非 const 对象,但不可以让指向非 const 对象的指针向 const 对象。
复制实参的局限性 复制实参并不是在所有的情况下都适合,不适宜复制实参的情况包括:
• 当需要在函数中修改实参的值时。
• 当需要以大型对象作为实参传递时。对实际的应用而言,复制对象所付出
的时间和存储空间代价往往过在。
• 当没有办法实现对象的复制时。
对于上述几种情况,有效的解决办法是将形参定义为引用或指针类型。
例如定义一个函数交换两个参数的值,就需要用引用形参
利用 const 引用避免复制(如果使用引用形参的唯一目的是避免复制实参,则应将形参定 义为 const 引用。)
bool isShorter(const string &s1, const string &s2)
{
return s1.size() < s2.size();
}
因为形参是引用,所以不复 制实参。又因为形参是 const 引用,所以 isShorter 函数不能使用该引用来修 改实参。
如果函数具有普通的非 const 引用形参,调用这样的函数时,传递一个右值(第 2.3.1 节) 或具有需要转换的类型的对象同样是不允许的:
应该将不修改相应实参的形参定义为 const 引用。
传递指向指针的引用
vector 和其他容器类型的形参
C++ 程序员倾向于通过传递指向容器中需要 处理的元素的迭代器来传递容器:
void print(vector<int>::const_iterator beg , vector<int>::const_iterator end)
{
while (beg != end) {
cout << *beg++;
if (beg != end) cout << " "; // no space after last element }
cout << endl;
}
这个函数将输出从 beg 指向的元素开始到 end 指向的元素(不含)为止的 范围内所有的元素
内联函数inline
把 inline 函数放入头文件
类的成员函数后面加 const,表明这个函数不会对这个类对象的数据成员(准确地说是非静态数据成员)作任何改变。
在设计类的时候,一个原则就是对于不改变数据成员的成员函数都要在后面加 const,而对于改变数据成员的成员函数不能加 const。所以 const 关键字对成员函数的行为作了更加明确的限定:有 const 修饰的成员函数(指 const 放在函数参数表的后面,而不是在函数前面或者参数表内),只能读取数据成员,不能改变数据成员;没有 const 修饰的成员函数,对数据成员则是可读可写的。
出现在相同作用域中的两个函数,如果具有相同的名字而形参表不同,则称为重
载函数。编译器将根据所传 递的实参类型来判断调用的是哪个函数。
如果两个函数声明的返回类型和形参表完全匹配,则将第二个函数声明视为第一 个的重复声明。如果两个函数的形参表完全相同,但返回类型不同,则第二个声 明是错误的:
Record lookup(const Account&);
bool lookup(const Account&); // error: only return type is different
函数不能仅仅基于不同的返回类型而实现重载。
指向函数的指针
bool (*pf)(const string &, const string &);
这个语句将 pf 声明为指向函数的指针,它所指向的函数带有两个 const string& 类型的形参和 bool 类型的返回值。
用 typedef 简化函数指针的定义,cmpFcn是一种指向函数的指针
typedef bool (*cmpFcn)(const string &, const string &)
通过指针调用函数
cmpFcn pf = lengthCompare;
lengthCompare("hi", "bye");