c++primer第五版----学习笔记(十八)Ⅱ

部分习题解答:

18.1
(a)range_error
(b)exception
如果写成throw p,则抛出指针,是错误的
18.2
发生异常,所在块之前的临时变量都会被销毁,v调用vector类的析构函数进行销毁,并释放相关内存;p指针会被销毁,但p指向的内存是动态分配的,所以该内存不会被销毁,输入流对象会调用ifstream类的析构函数进行销毁,最终程序被终止
18.3
我们要解决的问题是p指向的内存要被自动释放
第一种使用智能指针,并传入lambda表达式:

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


第二种构建一个包含int*类,并在析构函数中delete指针:

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

18.4
继承链最底端的类须放在前面,将顺序倒过来即可

18.5

#include <iostream>
#include <cstdlib>
using namespace std;

int main(int argc, char **argv)
{
	try {

	}
	catch (overflow_error o) {
		cout << o.what() << endl;
		abort();
	}
	catch (underflow_error u) {
		cout << u.what() << endl;
		abort();
	}
	catch (range_error r) {
		cout << r.what() << endl;
		abort();
	}
	catch (domain_error d) {
		cout << d.what() << endl;
		abort();
	}
	catch (invalid_argument i) {
		cout << i.what() << endl;
		abort();
	}
	catch (out_of_range o) {
		cout << o.what() << endl;
		abort();
	}
	catch (length_error l) {
		cout << l.what() << endl;
		abort();
	}
	catch (runtime_error r) {
		cout << r.what() << endl;
		abort();
	}
	catch (logic_error l) {
		cout << l.what() << endl;
		abort();
	}
	catch (bad_cast b) {
		cout << b.what() << endl;
		abort();
	}
	catch (bad_alloc b) {
		cout << b.what() << endl;
		abort();
	}
	catch (exception e) {
		cout << e.what() << endl;
		abort();
	}
	system("pause");
        return 0;
}

18.6
(a)throw &exception();
(b)任意异常
(c)throw int();
18.7:
将所有的构造函数添加这个try语句块

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

18.9

#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;
};

18.10
不捕获异常就会发生异常,程序报错并终止
18.11
what负责返回用于初始化异常对象的信息,如what抛出异常可能造成无限递归
18.13
希望定义的对象、函数、类类型或其他实体,它只在程序的一小段代码中可见,因为这样可以更进一步地缓解名字空间污染问题;在标准c++引入命名空间之前,用static进行静态声明,现在只使用未命名空间
18.14

mathLib::MatrixLib::matrix  mathLib::MatrixLib::operator*(const matrix &, const matrix &);


18.15:
using指示以关键字using开始,后面是关键字namespace以及命名空间的名字,using指示将命名空间中所有名字变得可见
using声明一次只引入命名空间的一个成员,两者作用域范围相同

18.16、18.17

namespace Exercise {
	int ivar = 0;
	double dvar = 0;
	const int limit = 1000;
}
int ivar = 0;
//1.1
using Exercise::ivar;//错误,与全局变量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;
	++::ivar;
}
//2.1
using namespace Exercise;
void manip()
{
	double dvar = 3.1416;  //覆盖using中的dvar
	int iobj = limit + 1;
	++ivar;          //错误,不明确,产生二义性
	++::ivar;
}
//2.2
void manip()
{
	using namespace Exercise;
	double dvar = 3.1416;  //覆盖using中的dvar
	int iobj = limit + 1;
	++ivar;          //错误,不明确,产生二义性
	++::ivar;
}

18.18
如mem1是string,则在string类中查找swap函数,找到则不使用std版本,若为int类型,则直接使用标准库中swap版本
18.19
只能使用标准库版本swap

18.20

namespace primerLib {
	void compute();  //不可行
	void compute(const void *);   //可行,0->NULL
}
using primerLib::compute;
void compute(int);    //可行
void compute(double, double = 3.4);  //可行,int->double
void compute(char*, char* = 0);  //可行,0->NULL
void f() {
	compute(0);  //与compute(int)最佳匹配
}
//2.0
namespace primerLib {
	void compute();  //不可行,可见
	void compute(const void *);   //可行,0->NULL,可见
}
void compute(int);    //可行,被隐藏
void compute(double, double = 3.4);  //可行,int->double,被隐藏
void compute(char*, char* = 0);  //可行,0->NULL,被隐藏
void f() {
	using primerLib::compute; 
	compute(0);  //与compute(const void *)最佳匹配 
}

18.21
(a)正确,公有继承CAD,私有继承Vehicle
(b)错误,继承相同的基类
(c)正确
18.22
构造函数执行顺序:A->B->C->X->Y->Z->MI
18.23
可以令一个基类指针或引用指向一个派生类对象
(a)允许         (b)允许
(c)允许         (d)允许
18.24
所有属于Bear类的成员将不能进行访问,只能访问属于ZooAnimal的成员
18.25

#include <iostream>
using namespace std;

class Base1 {
public:
      virtual void print()
      {
            cout << "Base1::print()" << endl;
      }
      virtual ~Base1()
      {
            cout << "~Base1()" << endl;
      }
};

class Base2 {
public:
      virtual void print()
      {
            cout << "Base2::print()" << endl;
      }
      virtual ~Base2()
      {
            cout << "~Base2()" << endl;
      }
};

class D1 : public Base1 {
public:
      void print()
      {
            cout << "D1:print()" << endl;
      }
      ~D1()
      {
            cout << "~D1()" << endl;
      }
};
class D2 : public Base2 {
public:
      void print()
      {
            cout << "D2.print()" << endl;
      }
      ~D2()
      {
            cout << "~D2()" << endl;
      }
};
class MI : public D1, public D2 {
public:
      void print()
      {
            cout << "MI::print()" << endl;
      }
      ~MI()
      {
            cout << "~MI()" << endl;
      }    
};

int main()
{
      Base1 *pb1 = new MI;
      Base2 *pb2 = new MI;
      D1 *pd1 = new MI;
      D2 *pd2 = new MI;
      pb1->print();c   //以下三个都是调用MI::print()
      pd1->print();
      pd2->print();
      delete pb2;   //以下三个都是调用MI的析构,调用D2的析构,调用Base2的析构,调用D1的析构,调用Base1的析构
      delete pd1;
      delete pd2;
      return 0;
}

 

 

 

 

 

 

 

 

 

 

 

 

 

18.26
参数为42(int),调用产生二义性,可以修改为
MI.Base1::print(42);
加上前缀限定符,直接调用Base1的成员
18.27
(a)
Base1: ival,dval,cval,print
Base2: fval,print
Derived: sval,dval,print
MI: ival,dvec,print,foo
还有在foo中定义的ival
(b)
dval:  Base1::dval, Derived::dval, MI成员函数foo中定义的dval
ival:  Base1::ival, MI::ival
cval:  Base1::cval, 形参cval
(c)
dval = Base1::dval + Derived::dval;
(d)
Base2::fval = MI::dvec.back();
(e)
Derived::sval[0]  = Base1::cval;

18.28

需要加限定符:foo(),cval

不需要加限定符:bar(),ival

18.29

(a)

构造顺序:Class、Base、D1、D2、MI、Final

析构顺序相反

(b)

一个Base部分,2个Class部分

(c)

1、错误,Class是Base的基类,而pb是Base类                2、正确,基类Class可以指向所有子类
3、错误、pb是Base类,MI是Base的子类                         4、正确、D2是MI的基类

18.30

class Class {};
class Base : public Class {
protected:
	int val;
public:
	Base() : val(0),Class() { }
	Base(const Base &a) = default;
	Base(int a) : val(a),Class() {}
};
class D1 : virtual public 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
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值