简单语句
C++语言中的大多数语句都以分号结束,一个表达式,比如 ival + 5,末尾加上分号就变成了表达式语句(expression statement)。表达式语句的作用是执行表达式并丢弃掉求值结果:
ival + 5;//一条没什么实际用处的表达式语句
cout << ival;//一条有用的表达式语句
空语句
最简单的语句是空语句(null statement),空语句中只含有一个单独的分号:
;//空语句
如果在程序的某个地方,语法上需要一条语句但是逻辑上不需要,此时应该使用空语句。一种常见的情况是,当循环的全部工作在条件部分就可以完成时,我们通常会用到空语句。
//重复读入数据直至到达文件末尾或某次输入的值等于sought
while(cin >>s && s != sought)
;//空语句
使用空语句应该加上注释。
别漏写分号,也别多写分号。多余的空语句并非总是无害的。
ival =vl +v2;;//正确:第二个分号表示一条多余的空语句
复合语句(块)
复合语句(compound statement) 是指用花括号括起来的(可能为空的)语句和声明的序列,复合语句也被称作块(block)。一个块就是一个作用域,在块中引入的名字只能在块内部以及嵌套在块中的子块里访问。
块不以分号作为结束。
while (cin >>s && s!=sought){
;
//空块
}
语句作用域
可以在 if、switch、while 和 for 语句的控制结构内定义变量。
定义在控制结构当中的变量只在相应语句的内部可见,一旦语句结束,变量也就超出其作用范围了;
while (int i = get_num()){ //每次迭代时创建并初始化i
cout<<i <<endl;
}
i=0;//错误:在循环外部无法访问i
如果其他代码也需要访问控制变量,则变量必须定义在语句的外部。
条件语句
if 语句:根据条件决定控制流;
switch 语句:计算一个整型表达式的值,然后根据这个值从几条执行路径中选择一条。
if 语句
判断一个指定的条件是否为真,根据判断结果决定是否执行另外一条语句。
//if else语句的形式是
if (condition)
statement
else
statement2
switch 语句
在若干固定选项中做出选择。
switch语句首先对括号里的表达式求值,该表达式紧跟在关键字 switch 的后面,可以是一个初始化的变量声明。表达式的值转换成整数类型,然后与每个 case 标签的值比较。
case 关键字和它对应的值一起被称为case标签(case label)。case标签必须是整型常量表达式。
switch(A){
case 1: ;break;
case 2: ;break;
case 3: ;break;
default: ;
}
如果没有任何一个 case 标签匹配 switch 表达式的值,就执行 default 分支。
即使不准备在 default 下做任何工作,也定义一个 default 标签。
如果要在 case 分支定义并初始化变量,应该定义在块内以约束其作用域。
迭代语句
迭代语句通常称为循环,它重复执行操作直到满足某个条件才停下来。while 和 for 语句在执行循环体之前检查条件,do while 语句先执行循环体,然后再检查条件。
while 语句
只要条件为真,while语句(while statement)就重复地执行循环体
while(condition){
statement
}
定义在while条件部分或者while循环体内的变量每次迭代都经历从创建到销毁的过程。
for 语句
一般情况下,init-statement 负责初始化一个值,这个值将随着循环的进行而改变。condition作为循环控制的条件,只要condition为真,就执行一次statement。
for(init-statemen; condition; expression){
statement
}
init-statement必须是:声明语句、表达式语句或者空语句三种形式中的一种。
for语句头中定义的对象只在for循环体内可见。
遍历容器和序列的 范围 for 语句
for (declaration : expression){
statement
}
expression 表示的必须是一个序列,比如用花括号括起来的初始值列表、数组或者vector或string等类型的对象,这些类型的共同特点是拥有能返回迭代器的 begin和 end成员。
declaration定义一个变量,序列中的每个元素都得能转换成该变量的类型。确保类型相容最简单的办法是使用 auto类型说明符,这个关键字可以令编译器帮助我们指定合适的类型。如果需要对序列中的元素执行写操作,循环变量必须声明成引用类型。
for (auto beg = v.begin(),end = v.end(); beg != end; ++beg){
auto &r = *beg;// r必须是引用类型,这样才能对元素执行写操作
r *= 2;//将v中每个元素的值翻倍
}
do while 语句
语句先执行循环体后检查条件。不管条件的值如何,都至少执行一次循环。
do{
statement
}while(condition);
跳转语句
break、continue、goto、return
break 语句
break语句(break statement)负责终止离它最近的 while、do while、for 或 switch 语句,并从这些语句之后的第一条语句开始继续执行。
continue 语句
continue 语句(continue statement)终止最近的循环中的当前迭代并立即开始下一次迭代。continue 语句只能出现在 for、while 和 do while 循环的内部,或者嵌套在此类循环里的语句或块的内部。
continue语句中断当前的迭代,但是仍然继续执行循环。
goto 语句
goto语句(goto statement)的作用是从goto语句无条件跳转到同一函数内的另一条语句。
不要在程序中使用goto语句。
goto label;//
//向后跳过一个带初始化的变量定义是合法的
begin:
int sz = get_size();
if(sz <= 0){
goto begin;
}
goto语句不能将程序的控制权从变量的作用域之外转移到作用域外。
如果 goto 语句跳回了一条变量的定义之前意味着系统将会销毁该变量,然后重新创建它。
try 语句块和异常处理
异常是指存在于运行时的反常行为,这些行为超出了函数正常功能的范围。
异常处理机制为程序中异常检测和异常处理这两部分的协作提供支持:
- throw表达式(throw expression),异常检测部分使用 throw 表达式来表示它遇到了无法处理的问题。我们说 throw 引发(raise)了异常。
- try语句块(try block),异常处理部分使用 try 语句块处理异常。try 语句块以关键字 try 开始,并以一个或多个 catch 子句(catch clause)结束。try 句块中代码抛出的异常通常会被某个 catch 子句处理。因为catch子句“处理”异常,所以它们也被称作异常处理代码(exception handler)。
- 一套异常类(exception class),用于在throw表达式和相关的catch子句之间传递异常的具体信息。
throw 表达式
程序的异常检测部分使用 throw 表达式引发一个异常。throw表达式包含关键字throw和紧随其后的一个表达式,其中表达式的类型就是抛出的异常类型。throw表达式后面通常紧跟一个分号,从而构成一条表达式语句。
if (item1 .isbn( != item2 .isbn())
throw runtime_error ( "Data must refer to same ISBN");
类型 runtime error 是标准库异常类型的一种,定义在 stdexcept 头文件中。
try 语句块
try语句块的一开始是关键字try,随后紧跟着一个块。
try {
program-statements
}catch (exception-declaration) {
handler-statements
}catch (exception-declaration) {
handler-statements
}//...
跟在try块之后的是一个或多个catch子句。catch 子句包括三部分:关键字catch、括号内一个(可能未命名的)对象的声明(称作异常声明,exception declaration)以及一个块。当选中了某个 catch 子句处理异常之后,执行与之对应的块。catch一旦完成,程序跳转到 try 语句块最后一个 catch 子句之后的那条语句继续执行。
while (cin >> item1 > item2) {
try {
//执行添加两个Sales_item对象的代码
//如果添加失败,代码抛出一个runtime_error异常
}catch (runtime_error err) {
//提醒用户两个ISBN必须一致,询问是否重新输入
cout <<err.what()
<<"\nTry Again? Enter y or n" << endl;
char c;
cin >>C;
if ( !cin ll c== 'n')
break;//跳出 while循环
}
}
编写异常安全的代码非常难
标准异常
'exception头文件'
exception // 异常类 exception 是最通用的异常类。它只报告异常的发生,不提供额外信息。
'new头文件'
bad_alloc // 异常类 bad_alloc。在使用 new 分配动态内存失败时抛出
'type_info头文件'
bad_cast // 异常类型 bad_cast。经常发生在使用 dynamic_cast 时发生。
'stdexcept头文件'
exception
runtime_error // 只有在运行时才能检测出的问题
range_error // 运行时错误:生成的结果超出了有意义的值域范围
overflow_error // 运行时错误:计算上溢
underflow_error // 运行时错误:计算下溢
logic_error // 程序逻辑错误
domain_error // 逻辑错误:参数对象的结果值不存在
invalid_argument // 逻辑错误:无效参数
length_error // 逻辑错误:试图创建一个超出该类型最大长度的对象
out_of_range // 逻辑错误:使用一个超出有效范围的值
重要术语
异常类(exception class) 是标准库定义的一组类,用于表示程序发生的错误。
异常声明(exception declaration) 位于catch 子句中的声明,指定了该catch子句能处理的异常类型。
异常安全(exception safe) 是一个术语,表示的含义是当抛出异常后,程序能执行正确的行为。