第十五章 15.5节练习

练习15.18

假设给定了第543页和544页的类,同时已知每个对象的类型如注释所示,判断下面的哪些赋值语句是合法的。解释哪些不合法的语句为什么不被允许:

Base *p = &d1; // d1的类型是Pub_Derv
p = &d2; // d2的类型是Priv_Derv
p = &d3; // d3的类型是Prot_Derv
p = &dd1; // dd1的类型是Derived_from_Public
p = &dd2; //dd2 的类型是Derived_from_Private
p = &dd3; //dd3 的类型是Derived_from_Protected

解答:

class Base{
public:
  Base() = default;
  void pub_mem(){};
protected:
  int prot_mem;
private:
  char priv_mem;
};

struct Pub_Derv: public Base{
  int f(){return prot_mem;}
};

struct Priv_Derv: private Base{
  int f1() const {return prot_mem;}
};

struct Prot_Derv: protected Base{
  int f2() const {return prot_mem;}
};

struct Derived_from_Public : public Pub_Derv{
  int use_base(){return prot_mem;}
};

struct Derived_from_Private: public Priv_Derv{

};

struct Derived_from_Protected: public Prot_Derv{
  int use_base(){return prot_mem;}
};

Pub_Derv d1;
Priv_Derv d2;
Prot_Derv d3;
Derived_from_Public dd1;
Derived_from_Private dd2;
Derived_from_Protected dd3;
以上是各个类的定义

  Base *p = &d1; // 合法
  p = &d2; // error: ‘Base’ is an inaccessible base of ‘Priv_Derv’
  p = &d3; // error: ‘Base’ is an inaccessible base of ‘Prot_Derv’
  p = &dd1; // 合法
  p = &dd2; // error: ‘Base’ is an inaccessible base of ‘Derived_from_Private’
  p = &dd3; // error:‘Base’ is an inaccessible base of ‘Derived_from_Protected’


练习15.19

假设543页和544页的每个类都有如下形式的成员函数:

void memfcn(Base &b){b = *this;}

对于每个类,分别判断上面的函数是否合法。

解答:

这个题稍稍有点绕,不过画个继承关系图,就很容易看出来了。(我用眼睛看了半天……悲剧的)

这里Pub_Derv、Priv_Derv、Prot_Derv,因为是直接继承于Base,所以做这个赋值操作肯定没有问题。

如果加入这个函数编译出现问题,那么一定在Derived_from_*类里面。

在Derived_from_*类里面Base可以看做一个成员,根据*_Derv的继承方式来来决定修饰符。

比如:Prot_Derv类以protected的方式继承Base,在Derived_from_Protected继承过程中中,就可以把Base当做Prot_Derv的一个protect的成员。

(我是这样理解的,不知道有没有更好的解释方式)

Derived_from_Public继承于Pub_Derv, Base相当于public成员,直接访问赋值没有问题。

Derived_from_Protected继承于Prot_Derv, Base相当于protected成员,直接访问赋值没有问题。

Derived_from_Private继承于Priv_Derv, Base相当于private成员,直接访问赋值有问题。


所以,在Derived_from_Private中添加以上函数就是非法的。


练习15.20

编写代码验证你得对前面两题的回答是否正确。

解答:

19题的错误信息:(from g++ 4.9.1)

error: ‘Base’ is an inaccessible base of ‘Derived_from_Private’


练习15.21

从下面这些一般性抽象概念中任选一个(或者选一个你自己的),将其对应的一组类型组支撑一个继承体系:

(a) 图形文件格式(如gif,tiff,jpeg,bmp)

(b) 图形基元(如方格,圆,球,圆锥)

(c) C++语言中的类型(如类,函数,成员函数)

解答:

这里图形基元应该更加直观一些,建议选这个吧。

比如圆吧,(我们的圆需要建立在笛卡尔坐标系中)

圆的最基本元素就是半径和远点,但是这只能被用于正圆。

我们希望圆的基元也能涵盖到椭圆,因为我们知道正圆是椭圆的一种特例。

所以,就要扩充圆点和半径等内容,肯那个就需要添加焦点,准线之类的成员变量。

当然,之后还需要去计算面积,重置一些成员变量,这时候就需要定义我们需要的成员函数了。


struct Point{
	double x;
	double y;
};

class cricle{
public:
	cricle() = default;
	virtual double area() = 0;
	virtual double circumference() = 0;

private:
	Point p;
};
椭圆可以继承这个基类。

尝试着实现了下椭圆的类,发现就是个坑呀,把高中数学复习了一下,忘得几乎差不多了,这里也就不放上来了(有点怀念matlib了)

PS 个人感觉这个基类也实现的不好,不过,格式上大家还是可以参照一下的。


练习15.22

对于你再上一题中选择的类,为其添加合适的虚函数及公有成员和受保护的成员。

解答:

这题就考虑要对类做一定的封装了。

当然,这个开始的时候大家可以随意设置,权当做练习。

但当涉及到真正的程序设计,就需要你去按照实际考虑哪些成员需要哪些修饰符进行修饰。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值