您的位置:首页 > 编程语言 > C语言/C++

C++Primer第五版 第十八章习题答案(1~10)

2017-03-20 09:26 567 查看
大规模应用程序的特殊要求
知识点1:异常处理:在独立开发的子系统之间协同处理错误的能力

知识点2:命名空间:使用各种库(可能包含独立开发的库)进行协同开发的能力

知识点3:多重继承:对比较复杂的应用概念建模的能力

1:知识点:C++通过抛出一个表达式来引发一个异常,throw之后的代码将不会被执行,程序控制权将从throw转移到与之匹配的catch模块(即捕获)(若try语句块还有嵌套,将继续在外层中寻找,称为栈展开),执行完这个catch语句之后,将转移到try块关联的最后一个catch子句之后的点,并从这里继续执行,若找不到与之匹配的catch语句,程序将调用标准库的terminate函数终止程序

答案:异常对象的类型皆是range_error

2:知识点1:栈展开的过程中对象会被自动销毁(所在块中创建的对象),若是类类型,该对象的析构函数将会自动执行

知识点2:析构函数总会执行,但是函数中负责释放资源的代码可能会被跳过(异常发生在负责释放资源的代码之前),但是类分配的对象无论函数正常结束还是遭遇异常,通过析构函数其资源都能够被正常释放(由于是自动执行的,所以析构函数中不应该抛出异常)

答案:发生异常,所在块之前的临时变量皆会被销毁,V会调用vector类的析构函数进行销毁,并释放相关内存,P指针会被销毁,但是P指针指向的内存由于是动态分配的,所以该内存不会被释放,造成内存泄漏。输入流对象会调用ifstream类的析构函数销毁,最后程序被终止

3:知识点1:throw抛出的表达式类型必须具有完全类型(如若是一个类,必须有完整的定义,不能仅仅只有声明)

知识点2:throw的抛出表达式若是一个指向局部对象的指针,那么肯定是错误的,因为其指向的内存会被释放,就类似于函数不能返回局部对象的指针一样(该块catch语句之前已经退出,对象已经被销毁)

知识点3:throw抛出的表达式是其静态编译的类型,也就是静态类型,所以不会发生动态绑定,若throw表达式解引用一个基类(基类的类型)指针,该指针指向的是派生类对象,则抛出的对象会被切除其派生类的部分

答案:只有指针P所分配的内存会出现错误,所以我们需要解决的问题是怎样在发生异常时,自动释放其指向的内存

1:使用智能指针,并传入删除的lambda表达式

shared_ptr<int> p(new int[v.size()], [](int *p) { delete[] p; });//lambda表达式相当于一个删除器


2:使用类:创建一个包含一个int*的类,在析构函数进行delete文件指针

class intAr
{
int *p=nullptr;
public:
intAr(size_t n):p(new int
){}
~intAr()
{
delete[]p;
}
}


4:知识点1:catch子句中的异常声明看起来像是函数的形参列表,但是这个类型必须是完全类型,不能是右值引用。若其参数类型是非引用,则会传入一份异常对象的副本,若是引用,则是该对象的别名。

知识点2:若catch的参数是基类类型,我们可以使用派生类类型的异常声明对其进行初始化,如若不是引用方式,则会将派生类的部分切除。

知识点3:搜索匹配的catch语句过程中,找到的未必是最佳匹配,是第一个可以匹配的catch语句,所以越是专门、越是特例化的catch语句应该放在前面,因为catch语句是按照其出现顺序逐一匹配的

知识点4:catch语句参数类型允许的类型转换:非const到const、派生类到基类、数组元素到指针、函数名到指针这四种类型转换被允许

知识点5:若所个catch语句的类型之间存在这继承关系,应该将继承链的最低端的类放在前面

答案:由知识点3、5可知,应该将继承最低端的类放在最前面,顺序倒过来即可

5:复习一下P173相关知识,知识点:每个标准库异常类都包含了一个名为what的成员函数,这个函数没有参数,返回值是C风格的字符串(const char *),注意第四题知识点5

#include <iostream>
#include <cstdlib>
int main()
{
using namespace std;
try {
//
}
catch (overflow_error e)
{
cout << e.what();
abort();
}
catch (underflow_error u)
{
cout << u.what();
abort();
}
catch (range_error r)
{
cout << r.what();
abort();
}
catch (domain_error d)
{
cout << d.what();
abort();
}
catch (invalid_argument i)
{
cout << i.what();
abort();
}
catch (out_of_range o)
{
cout << o.what();
abort();
}
catch (length_error l)
{
cout << l.what();
abort();
}
catch (runtime_error r)
{
cout << r.what();
abort();
}
catch (logic_error l)
{
cout << l.what();
abort();
}
catch (bad_alloc b)
{
cout << b.what();
abort();
}
catch (bad_alloc b)
{
cout << b.what();
abort();
}
catch (exception e)
{
cout << e.what();
abort();
}

return 0;
}


6:知识点1:捕获所有异常的处理代码:catch(...)可以与任何类型的异常匹配,左一该语句必须放在catch列表的最后位置

知识点2:catch语句通过重新抛出的操作将异常传递给另外一个catch,只需要在其体内加 throw;,通常情况下是因为catch语句需要改变其参数的内容,并想继续传播

(a):throw &exceptionType()

(b):任何异常皆可

(c):throw int()

7:知识点1:由于构造函数在其进入函数体之前进行初始化(执行初始化列表),所以此时的try语句块还未生效,所以构造函数体内的catch语句无法处理构造函数初始值列表抛出的异常,这是就需要构造函数try语句块的形式,即将初始值列表置于try语句块中(try语句块出现在:冒号之后以及函数体的花括号之前)

所有的构造函数都添加这个try语句块即可

template<typename T>
Blob<T>::Blob() try:data(std::make_shared<std::vector<T>>()) {
}
catch (const std::bad_alloc &e) {
std::cerr << e.what() << std::endl;
}


8:知识点1:noexcep异常说明可以用来指定某个函数不会抛出异常(C++11新特性),声明和定义时皆需要出现在函数之后,但在final、override、=0之前

知识点2:noexcept用于两种情况:1:确认函数不会抛出异常 2:我们不知道如何处理异常

知识点3:异常说明还可以有实参,为bool类型,为true时,则函数不会抛出异常,为false时会抛出异常

知识点4:noexcept还可以作为运算符来使用,当其不跟在函数参数列表之后时,返回值是一个bool的常量表达式,为true时,表明传入参数会抛出异常

知识点5:函数指针和该指针所指的函数必须具有一致的异常说明

知识点6:如果一个虚函数承诺不抛出异常,则其派生类的相应虚函数需要作出同样的承诺

知识点7:若对所有成员和基类的操作都是noexcept的,则编译器合成版本的成员也是noexcept的

9:知识点1:exception表示的含义是某处出错,但错误细节未知,what是一个虚函数,所以引用捕获时会发生动态绑定

知识点2:自己定义的异常类型和标准库的异常类处理方式完全一样,一处抛出一处捕获

主要理解isbn_mismatch其实是一个继承的异常类

#include <iostream>
#include <string>
//18.9
struct out_of_stock :public std::runtime_error
{
explicit out_of_stock(const std::string &s) :std::runtime_error(s) {}
};

struct isbn_mismatch :public std::logic_error
{
explicit isbn_mismatch(const std::string &s) :std::logic_error(s) {}
isbn_mismatch(const std::string &s, const std::string &ls, const std::string &rs)
:std::logic_error(s), left(ls), right(rs)
{}
std::string left;
std::string right;
};


10:不捕获就发生异常,报错退出呗
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息