C++primer18章课后答案

C++primer18章课后答案

18.1
(a)的异常对象类型为range_error
(b)的异常对象类型为exception
因为异常类型的对象类型是由表达式在编译时的静态类型决定的。
如果写成了throw p,在抛出异常对象p时调用终止
18.2
vector会调用自己的析构函数销毁自身
动态分配的内存空间将不会被释放
in内存储的对象被销毁
18.3
第一种方法是使用一个类管理动态数组

template<typename T>
struct DynamicArry
{
    explicit DynamicArry(size_t n) :ptr(new T[n]) {}
    ~DynamicArry() { delete []ptr; }
    T* ptr;
};

第二种方法是使用智能指针管理

std::shared_ptr<int> p(new int[v.size()], [](int* p) {delete[] p; })

18.4
顺序错误,应该把继承链最底端的类放在前面。
18.5

int main()
{
    try {
        //使用C++标准库
    }
    catch(...)
    {
        //处理异常
    }
}

18.6


#include <iostream>
#include<cstdlib>
int main()
{
    try {
        //使用C++标准库
    }
    catch(std::exception&e)
    {
        std:: cout << e.what() << std::endl;
        abort();
    }
}

18.6
(a)throw new exceptionType();
(b)throw exception();
(c)throw 1;
18.7

StrBlob::StrBlob()try :data(make_shared<vector<string>>()) {}
catch (...) { cout << "StrBlob constructor error" << endl; };

18.8

18.9

Sales_data& Sales_data::operator +=(const Sales_data& rhs)
{
    if (isbn() != rhs.isbn())
        throw isbn_mismatch("wrong isbn", isbn(), rhs.isbn());
    this->revenue += rhs.revenue;
    this->units_sold += rhs.units_sold;
    return *this;
}
class out_of_stock :public std::runtime_error
{
public:
    explicit out_of_stock(const std::string& msg) :std::runtime_error(msg) {}
};
class isbn_mismatch :public std::logic_error
{
public:
    explicit isbn_mismatch(const std::string& s, const std::string& l, const std::string& r) :std::logic_error(s), left(l), right(r) {}
    const std::string left, right;
};

18.10
未被捕获的异常会导致程序异常退出。

int main()
{
	Sales_data s1("0123");
	Sales_data s2("3210");
	try { s1 += s2; }
	catch (isbn_mismatch& e)
	{
		cerr << e.what() << " :left isbn(" << e.left << ") right isbn(" << e.right << ")" << endl;
	}
}

18.11
what函数是用来处理异常信息的,如果what函数会抛出异常,会造成无限递归。
18.12

18.13
希望定义的类类型,对象,函数,或其他实体只在当前一个文件可见时使用,在C++11中static声明已经被取消了,使用未命名空间代替。
18.14

mathLib::MatrixLib::matrix mathLib::MatrixLib::operator*(matrix &a,matrix &b);

18.15

  • using声明:一次只能引入命名空间的一个成员,其有效范围从using声明开始,到using声明所在的作用域结束为止
  • using指示:与using声明类似,using namespace XX,将XX命名空间的所有成员变成可见,作用域和using声明一致。using指示一般被看作是出现在最近的外层作用域中,若有同名冲突成员,应加限定符予以区分
    18.16
namespace Exercise
{
	int ivar = 0;
	double dvar = 0;
	const int limit = 1000;
}
int ivar = 0;
//1.1  
//using Exercise::ivar;//错误,重定义,多次初始化
//using Exercise::dvar;  
//using Exercise::limit;  
//void manip()  
//{  
//  double dvar = 3.1416;//覆盖using声明的dvar  
//  int iobj = limit + 1;  
//  ++ivar;  
//  ++::ivar;  
//}  


//1.2  
//void manip()  
//{  
//  using Exercise::ivar;//隐藏全局变量  
//  using Exercise::dvar;  
//  using Exercise::limit;  
//  double dvar = 3.1416;//错误,重定义,多次初始化
//  int iobj = limit + 1;  
//  ++ivar;//Exercise的ivar  
//  ++::ivar;//全局变量  
//}  

//2.1  
//using namespace Exercise;  
//void manip()  
//{  
//  double dvar = 3.1416;//覆盖using声明的dvar  
//  int iobj = limit + 1;  
//  ++ivar;//错误,不明确,二义性,可能是int ivar或int Exercise::ivar 
//  ++::ivar;  
//}  

//2.2  
//void manip()  
//{  
//  using namespace Exercise;  
//  double dvar = 3.1416;//覆盖using声明的dvar  
//  int iobj = limit + 1;  
//  ++ivar;//错误,不明确,二义性,二者都可见  
//  ++::ivar;  
//}  
int main()
{
	manip();
}

18.17
见上题
18.18
当使用string时,在string类中查找,如果查找不到,则在std命名空间中查找。使用int时在标准库中查找,使用标准库中的swap
18.19
直接使用标准库版本的swap
18.20
来源

  • using指示将命名空间的成员提升到外层作用域中,若两空间有同名函数,则会被添加到重载集合中,且引入一个与已有函数形参列表完全相同的函数不会造成错误,只要我们指明使用哪个版本的函数即可
  • using声明引入的函数将重载该声明语句所属作用域中已有的同名函数,如果using声明出现在局部作用域中,则引入的名字会隐藏外层作用域中的同名声明
namespace p  
{  
    void compute();//不可行  
    void compute(const void *);//可行,0->NULL  
}  
using p::compute;  
void compute(int);//可行,最佳匹配  
void compute(double, double = 1.1);//可行,int->double  
void compute(char*, char* = 0);//可行,0->NULL  
  
void f()  
{  
    compute(0);
}  
namespace p{  
    void compute();//不可行,可见  
    void compute(const void *);//可行,0->NULL,可见  
}  
void compute(int);//可行,不可见,被隐藏
void compute(double, double = 1.1);//可行,int->double,被隐藏 
void compute(char*, char* = 0);//可行,0->NULL,被隐藏
void f(){  
    using p::compute;  
    compute(0);
}  

18.21

  • 缺少一个说明符
  • 派生列表不能有同名基类
  • 正确

18.22
执行顺序为A-B-C-X-Y-Z-MI
18.23
都允许,但是一个基类的指针只能访问基类部分和基类的基类部分。
18.24

ZooAnimal *pz=new Panda("ying_yang");
pz->print();//正确,使用Panda::print
pz->cuddle();//错误,不属于ZooAnimal接口
pz->toes();//错误,不属于ZooAnimal接口
pz->highlight();//错误,不属于ZooAnimal接口
delete pz;//正确,调用~Panda();

18.25
调用析构函数顺序与构造函数相反

(a)MI::print()
(b)MI::print()
( c)MI::print()
(d)~MI() ~D2() ~B2() ~D1() ~B1()
(e)~MI() ~D2() ~B2() ~D1() ~B1()
(f)~MI() ~D2() ~B2() ~D1() ~B1()
18.26
二义性,应该声明使用的是哪个类的print()函数,修改为mi.Base1::print()
18.27
(a)

  • Base1:int ival,char cval,int *id,print;
  • Base2: double fval,print
  • Derived:string sval,print
  • MI:int*ival,vector<double>dvec,print,foo
  • 还有foo中定义的dval
    (b)
    ival,print,cval,dval
    (c )
dval=Base1::dval+Derived::dval;

(d)

fval=dvec.back();

(e)

sval=Base1::cval;

18.28
可以直接访问的有Derived2::ival;void Derived1::bar(),其他需要加访问限定符
18.29
(a)构造函数顺序:Class,base,D1,D2,MI,Class
析构函数顺序相反
(b)一个base,两个Class
(c)

  • 错误,Class类是base的父类
  • 正确,Class类可以指向所有的子类
  • 错误,Base类是MI类的父类
  • 正确,D2是MI类的父类

18.30


> class Class {};
class Base :public Class {

protected:
    int ival;
public:
    Base() :ival(0), Class() {};
    Base(const Base& b) = default;
    Base(int a) :ival(a), Class() {}
};
class D1 :public virtual Base {
public:
    D1() :Base() {}
    D1(const D1& b) = default;
    D1(int a) :Base(a) {}
};
class D2 :public virtual Base {
public:
    D2() :Base() {}
    D2(const D2& b) = default;
    D2(int a) :Base(a) {}
};
class MI :public D1, public D2 {
public:
    MI() {}
    MI(const MI& m) :Base(m), D1(m), D2(m) {}
    MI(int i) :Base(i), D1(i), D2(i) {}
};
class Final :public MI, public Class {
public:
    Final() {}
    Final(const Final& f) : Base(f), MI(f), Class() {}
    Final(int i) : Base(i), Class() {}
};

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值