C++Prime 第十八章
练习18.1
(a) r是一个range_error类型对象
(b) p是exception
练习18.2
v被摧毁,p指针销毁,但是所指内存没有得到释放,in自动调用析构函数.
未找到catch,系统调用terminate函数,程序终结.
练习18.3
方案一:对p使用智能指针,补充try-catch语句
方案二:p改为全局对象
练习18.4
exception是基类,runtime_error也是overflow_error的基类,基类的捕获语句应该放在后面
try {
}
catch (overflow_error eobj) {
}
catch (const runtime_error& re) {
}
catch (exception) {
}
练习18.5
try {
//something
}
catch (range_error r) {
cerr << r.what();
abort();
}
catch (underflow_error u) {
cerr << u.what();
abort();
}
catch (overflow_error o) {
cerr << o.what();
abort();
}
catch (runtime_error r) {
cerr << r.what();
abort();
}
catch (length_error l) {
cerr << l.what();
abort();
}
catch (out_of_range o) {
cerr << o.what(); abort();
}
catch (invalid_argument i) {
cerr << i.what(); abort();
}
catch (domain_error d) {
cerr << d.what(); abort();
}
catch (logic_error l) {
cerr << l.what(); abort();
}
catch (bad_cast b) {
cerr << b.what(); abort();
}
catch (bad_alloc c) {
cerr << c.what(); abort();
}
catch (exception e) {
cout << e.what(); abort();
}
catch (...) {
throw;
}
练习18.6
(a) throw exceptionType();
(b) throw;
© throw EXCPTYPE();
练习18.7
Blob()try :m_mem(mem) { }
catch{
;
}
练习18.8
尽量规范代码,抛异常该处理就处理.
练习18.9
class out_of_stock :public std::runtime_error {
public:
explicit out_of_stock(const std::string& s) :std::runtime_error(s) { }
};
class isbn_mismatch :public std::logic_error {
public:
explicit isbn_mismatch(const std::string& s) :logic_error(s) { }
isbn_mismatch(const string& s, const string& lhs, const string& rhs) :
logic_error(s), left(lhs), right(rhs) { }
const string left, right;
};
Sales_data& Sales_data::operator+=(const Sales_data& rhs) {
if (isbn() != rhs.isbn())
throw isbn_mismatch("wrong isbn", isbn, rhs.isbn());
;//...
}
练习18.10
未捕获异常时,调用terminate,程序被终结.
练习18.11
what函数的使用基本是在catch异常处理语句里,如果抛出异常,就可能导致上一个异常还未处理完毕,又要去处理新的异常.
练习18.12
namespace{}
namespace{}
namespace{}
练习18.13
限定仅对当前文件有效时,使用匿名的命名空间
练习18.14
mathLib::MatrixLib::matrix mathLib::MatrixLib::matrix ::operator*(const matrix& x,const matrix&);
//or
using mathLib::MatrixLib::matrix;
matrix matrix::operator*();
练习18.15
using指示:将命名空间中的所有名字设置为可见,提示它们的作用域,会带来命名空间的污染.
using声明:一次只声明一个名字可用.
练习18.16
位置1 using声明:
dvar 是3.1416
iobj是1001
ivar会报错
++::ivar还是会报错
位置2 using声明:
dvar 报错.
iobj不变
++ivar是E类中的ivar
++::ivar是全局中的
练习18.17
namespace Ex {
int ivar = 0;
double dvar = 0;
const int limit = 0;
}
int ivar = 0;
using Ex::ivar;
using Ex::dvar;
using Ex::limit;
void manip() {
double dvar = 3.14;
int iobj = limit + 1;
++ivar;
++::ivar;
}
练习18.18
string类会首先查找string类,找不到swap的定义再查找std,而int会直接使用std
练习18.19
直接使用std版本的swap
练习18.20
void computer(int)会与之匹配
候选函数就是所有列出的computer
可行函数是:
computer(const void*)
(int),(double,double = 3.4),(char*,char* = 0);
此时只有compute(const void*)和compute()为候选函数,可行函数和最佳匹配就是带参版本了.
练习18.21
(a)多重继承
(b)错误,不可以继承同一个类两次
©正确
练习18.22
A->B->C->X->Y->Z->MI
练习18.23
(a)允许
(b)允许.A是D的基类,指向A的指针可以指向D
©允许.
(d)允许.
练习18.24
只能调用属于zoomanimal的部分
练习18.25
struct Base1 {
virtual ~Base1() { cout << "Base1" << endl; }
virtual void print(){ cout << "Base1" << endl; }
};
struct Base2 {
virtual ~Base2() { cout << "Base2" << endl; }
virtual void print() { cout << "Base2" << endl; }
};
struct D1:public Base1
{
virtual ~D1(){ cout << "D1" << endl; }
virtual void print() { cout << "D1" << endl; }
};
struct D2 :public Base2
{
virtual ~D2() { cout << "D2" << endl; }
virtual void print() { cout << "D2" << endl; }
};
struct MI :public D1, public D2 {
virtual ~MI() { cout << "MI" << endl; }
virtual void print() { cout << "MI" << endl; }
};
int main()
{
Base1* pb1 = new MI;
Base2* pb2 = new MI;
D1* pd1 = new MI;
D2* pd2 = new MI;
delete pb2;
return 0;
}
验证后的结果如下:
(a) MI::print()
(b) MI->print
© MI->print
(d) ~MI() - > ~D2() -> ~Base2() -> ~D1() ->Base1()
(e) ~MI() - > ~D2() -> ~Base2() -> ~D1() ->Base1()
(f) ~MI() - > ~D2() -> ~Base2() -> ~D1() ->Base1()
练习18.26
mi对于print的调用,会导致在其成员中查找print,其成员中有一个接受vector < double>的print,传来的形参是int,不匹配.
然后mi去其基类查找,这时不会查找形参和返回类型,而是查找名字,显然有同名,二义性调用,报错.
修改:加上作用域限定符
练习18.27
(a)ival,dval(int版),sval,fval,print(vector)
(b)
©
(d)
(e)
太难了,一时半半半会用不到,告辞.
练习18.28
练习18.29
(a)base ,Class, MI, D1,D2,Class,Final
(b)1个base,虚继承,两个class,继承了两次
©
a)错误,派生类指针不能用基类初始化
b)正确.
c)错误.
d)正确
练习18.30
暂时不做.