8C第八章习题解答.docx

上传人:b****7 文档编号:10095398 上传时间:2023-02-08 格式:DOCX 页数:45 大小:48.03KB
下载 相关 举报
8C第八章习题解答.docx_第1页
第1页 / 共45页
8C第八章习题解答.docx_第2页
第2页 / 共45页
8C第八章习题解答.docx_第3页
第3页 / 共45页
8C第八章习题解答.docx_第4页
第4页 / 共45页
8C第八章习题解答.docx_第5页
第5页 / 共45页
点击查看更多>>
下载资源
资源描述

8C第八章习题解答.docx

《8C第八章习题解答.docx》由会员分享,可在线阅读,更多相关《8C第八章习题解答.docx(45页珍藏版)》请在冰豆网上搜索。

8C第八章习题解答.docx

8C第八章习题解答

第八章继承与多态习题

一.基本概念与基础知识自测题

8.1填空题

8.1.1如果类α继承了类β,则类α称为

(1)类,而类β称为

(2)类。

(3)类的对象可作为(4)类的对象处理,反过来不行,因为(5)。

如果强制转换则要注意(6)。

答案:

(1)基类

(2)派生类

(3)派生类

(4)基类

(5)派生类有一些新成员

(6)只能派生类强制转换为基类

8.1.2当用public继承从基类派生一个类时,基类的public成员成为派生类的

(1)成员,protected成员成为派生类的

(2)成员,对private成员是(3)。

公有派生可以使其类的(4),所以公有派生是主流。

答案:

(1)public成员

(2)protected成员

(3)不可访问

(4)接口不变

8.1.3利用继承能够实现

(1)。

这种实现缩短了程序开发的时间,VC++中的

(2)很好地体现了这一点。

答案:

(1)代码的复用

(2)MFC编程

8.1.4一个派生类只有一个直接基类的情况称为

(1),而有多个直接基类的情况称为

(2)。

继承体现了类的(3)概念,这在MFC中得到了很好表现,MFC中只采用了(4)。

答案:

(1)单继承

(2)多重继承

(3)层次

(4)单继承

8.1.5C++中多态性包括两种多态性:

(1)和

(2)。

前者是通过(3)实现的,而后者是通过(4)和(5)来实现的。

答案:

(1)编译时的

(2)运行时的

(3)函数和运算符的重载

(4)类继承关系

(5)虚函数

8.1.6在基类中将一个成员函数说明成虚函数后,在其派生类中只要

(1)、

(2)和(3)完全一样就认为是虚函数,而不必再加关键字(4)。

如有任何不同,则认为是(5)而不是虚函数。

除了非成员函数不能作为虚函数外,(6)、(7)和(8)也不能作为虚函数。

答案:

(1)同虚函数名

(2)同参数表

(3)同返回类型。

如基类中返回基类指针,而派生类中返回派生类指针是允许的

(4)virtual

(5)重载

(6)静态成员函数

(7)内联函数

(8)构造函数

8.1.7纯虚函数定义时在函数参数表后加

(1),它表明程序员对函数

(2),其本质是将指向函数体的指针定为(3)。

答案:

(1)=0

(2)不定义

(3)NULL

8.2简答题

8.2.1构造函数和析构函数可以继承吗?

派生类构造函数各部分的执行次序是怎样的?

答:

构造函数和析构函数不可以继承。

派生类构造函数各部分的执行次序是:

1.调用基类构造函数,按它们在派生类声明的先后顺序,依次调用。

2.调用新增成员对象的构造函数,按它们在类定义中声明的先后顺序,依次调用。

3.派生类的构造函数体中的操作。

8.2.2什么叫派生类的同名覆盖(override)?

答:

如果派生类声明了一个和某个基类成员同名的新成员(当然如是成员函数,参数表也必须一样,否则是重载),派生类中的新成员就屏蔽了基类同名成员,类似函数中的局部变量屏蔽全局变量。

称为同名覆盖(override)。

8.2.3派生类的析构函数中需完成什么任务?

是否要编写对基数和成员对象的析构函数的调用?

为什么?

答:

析构函数的功能是作善后工作,析构函数无返回类型也没有参数,情况比较简单。

派生类析构函数定义格式与非派生类无任何差异,不要编写对基数和成员对象的析构函数的调用,只要在函数体内把派生类新增一般成员处理好就可以了,因为对新增的成员对象和基类的善后工作,系统会自己调用成员对象和基类的析构函数来完成。

8.2.4为什么要使用虚基类?

怎样定义虚基类?

用一个实例来解释虚基类在其派生类中的存储方式。

答:

在多重继承是有可能出现同一基类的两个拷贝,为避免这种情况,可使用虚基类。

虚基类(virtualbaseclass)定义方式如下:

class派生类名:

virtual访问限定符基类类名{...};

class派生类名:

访问限定符virtual基类类名{...};

virtual关键字只对紧随其后的基类名起作用。

如下派生:

存储关系如(b),在职研究生类有两个Person拷贝。

采用虚基类后存储关系如下:

在职研究生类只有一个Person拷贝。

8.2.5简单叙述派生类与基类的赋值兼容规则。

答:

凡是基类所能解决的问题,公有派生类都可以解决。

在任何需要基类对象的地方都可以用公有派生类的对象来代替,这条规则称赋值兼容规则。

它包括以下情况:

1.派生类的对象可以赋值给基类的对象,这时是把派生类对象中从对应基类中继承来的成员赋值给基类对象。

反过来不行,因为派生类的新成员无值可赋。

2.可以将一个派生类的对象的地址赋给其基类的指针变量,但只能通过这个指针访问派生类中由基类继承来的成员,不能访问派生类中的新成员。

同样也不能反过来做。

3.派生类对象可以初始化基类的引用。

引用是别名,但这个别名只能包含派生类对象中的由基类继承来的成员。

8.2.6在类中定义对象成员称为复合或嵌套,请对比复合与继承的异同之处。

答:

成员对象是嵌套的概念,使用成员对象中的成员,只能直接访问(对象名加点号加成员名)公有成员。

在类的成员函数中不能直接访问和处理成员对象的私有和保护成员,而要通过成员对象的接口去间接访问和处理。

某些应用中,对象成员可以代替继承中的基类。

基类在派生类中只能继承一个(间接基类不在讨论之中)不能同时安排两个,否则成员名即使使用域分辨符也会发生冲突,但如果一定要用两个,只能采用成员对象。

所以采用成员对象更加灵活。

两者不是对立的,而是互为补充的。

8.2.7比较派生与模板各自的优点。

答:

模板追求的是运行效率,而派生追求的是编程的效率。

通用性是模板库的设计出发点之一,这是由泛型算法和函数对象等手段达到的。

为了运行的效率,类模板是相互独立的,即独立设计,没有使用继承的思想。

对类模板的扩展是采用适配子(adapter)来完成的。

应该说派生类的目标之一也是代码的复用和程序的通用性,最典型的就是MFC,派生类的优点是可以由简到繁,逐步深入,程序编制过程中可以充分利用前面的工作,一步步完成一个复杂的任务。

8.2.8是否使用了虚函数就能实现运行时的多态性?

怎样才能实现运行时的多态性?

答:

不是。

实现动态多态性时,必须使用基类类型的指针变量或引用,使该指针指向该基类的不同派生类的对象,并通过该指针指向虚函数,才能实现动态的多态性。

8.2.9为什么析构函数总是要求说明为虚函数?

答:

在基类中及其派生类中都动态分配内存空间时,必须把析构函数定义为虚函数,实现撤消对象时的多态性。

根据赋值兼容规则可以用基类的指针指向派生类对象,如果由该指针撤销派生类对象,则必须将析构函数说明为虚函数,实现多态性,自动调用派生类析构函数。

我们总是要求将类设计成通用的,无论其他程序员怎样调用都必须保证不出错,所以必须把析构函数定义为虚函数。

8.2.10什么是抽象类?

含有纯虚函数的类是抽象类吗?

答:

若定义一个类,它只能用作基类来派生出新的类,而不能用来定义对象,则称为抽象类。

含有纯虚函数的类是抽象类。

8.2.11能否不提供源代码,做到用户自行把通用的软件转化为专用软件?

怎样实现?

答:

能不提供源代码,做到用户自行把通用的软件转化为专用软件。

动态联编不一定要源代码,可以只有头文件和对象文件的.obj文件。

软件开发商可在不透露其秘密的情况下发行.obj形式的软件,然后由程序员利用继承机制,从所购得的类中派生出新类。

能与软件开发商提供的类一起运行的软件也能与派生类一起运行,并能通过动态联编使用这些派生类中重定义的虚函数。

比如通用的财务软件可以转化为某公司的专用软件。

二.编程与综合练习题

8.3请用类的派生方式来组织下列动物实体与概念:

动物,脊椎动物亚门,节肢动物门,鱼纲,鸟纲,爬行纲,哺乳纲,昆虫纲,鲨鱼,青鱼,海马,鹦鹉,海鸥,喜鹊,蝙蝠,翼龙,蜻蜓,金龟,扬子鳄,袋鼠,金丝猴,虎,蜈蚣,蜘蛛,蝗虫,知了,螃蟹,虾。

解:

动物派生出:

脊椎动物亚门和节肢动物门。

脊椎动物亚门派生出:

鱼纲,鸟纲,爬行纲,哺乳纲。

鱼纲派生出:

鲨鱼,青鱼,海马。

鸟纲派生出:

鹦鹉,海鸥,喜鹊。

爬行纲派生出:

翼龙,金龟,扬子鳄。

哺乳纲派生出:

蝙蝠,袋鼠,金丝猴,虎。

节肢动物门派生出:

昆虫纲,蜈蚣(多足纲),蜘蛛(蜘形纲),螃蟹,虾(甲壳纲)。

昆虫纲派生出:

蜻蜓,蝗虫,知了。

8.4定义商品类及其多层的派生类。

以商品类为基类。

第一层派生出服装类、家电类、车辆类。

第二层派生出衬衣类、外衣类、帽子类、鞋子类;空调类、电视类、音响类;自行车类、轿车类、摩托车类。

要求给出基本属性和派生过程中增加的属性。

解:

按题意没有操作,所以只列出数据成员,也不再检验

#include

usingnamespacestd;

classCommodity{

doubleprice;//价格

charname[20];//商品名

charmanufacturer[20];//生产厂家

intitems;//数量

};

classClothing:

publicCommodity{//服装类

chartexture[20];//材料质地

};

classElectric_Appliance:

publicCommodity{//家电类

enum{Black,White}type;//黑白家电

};

classVehicle:

publicCommodity{//车辆类

intwheel_num;//车轮数量

};

classShirt:

publicClothing{//衬衣类

enum{Formal,Casual}Style;//式样:

正式、休闲

};

classGarment:

publicClothing{//外衣类

enum{Jacket,Coat}Style;//式样:

夹克、外套

};

classHat:

publicClothing{//帽子类;

enum{Winter,Summer,Spring_Autumn}Style;//季节风格

};

classShoes:

publicClothing{//鞋子类

enum{Winter,Summer,Spring_Autumn}Style;//季节风格

};

classAir_Cindition:

publicElectric_Appliance{//空调

boolwarm_cool;//是否冷暖

floatpower;//功率

};

classTelevision:

publicElectric_Appliance{//电视类

intSize;//尺寸

boolisColor;//是否彩色

};

classAcoustics:

publicElectric_Appliance{//音响类

intspeaker_num;//喇叭数目

floatpower;//功率

};

classBicycle:

publicVehicle{//自行车类

intspeed_grades;//调速级数

intwheel_size;//轮子大小

};

classCar:

publicVehicle{//轿车类

floatvolume;//排气量

boolisSkylight;//是否有天窗

intbox_num;//厢数

};

classMotorcycle:

publicVehicle{//摩托车类

floatvolume;//排气量

};

intmain(){

return0;

}

8.5以点(point)类为基类,重新定义矩形类和圆类。

点为直角坐标点,矩形水平放置,由左下方的顶点和长宽定义。

圆由圆心和半径定义。

派生类操作判断任一坐标点是在图形内,还是在图形的边缘上,还是在图形外。

缺省初始化图形退化为点。

要求包括拷贝构造函数。

编程测试类设计是否正确。

解:

#include

#include

usingnamespacestd;

constdoublePI=3.35;

classPoint{

private:

doublex,y;

public:

Point(){x=0;y=0;}

Point(doublexv,doubleyv){x=xv;y=yv;}

Point(Point&pt){x=pt.x;y=pt.y;}

doublegetx(){returnx;}

doublegety(){returny;}

doubleArea(){return0;}

voidShow(){cout<<"x="<

};

classCircle:

publicPoint{

doubleradius;

public:

Circle(){radius=0;}

Circle(doublexv,doubleyv,doublevv):

Point(xv,yv){radius=vv;}

Circle(Circle&cc):

Point(cc){radius=cc.radius;}//拷贝构造函数

doubleArea(){returnPI*radius*radius;}

voidShow(){//注意怎样访问基类的数据成员

cout<<"x="<

}

intposition(Point&pt){

doubledistance=sqrt((getx()-pt.getx())*(getx()-pt.getx())

+(gety()-pt.gety())*(gety()-pt.gety()));

doubles=distance-radius;

if(s==0)return0;//在圆上

elseif(s<0)return-1;//在圆内

elsereturn1;//在圆外

}

};

classRectangle:

publicPoint{

doublewidth,length;

public:

Rectangle(){width=0;length=0;}

Rectangle(doublexv,doubleyv,doublewv,doublelv):

Point(xv,xv){

width=wv;

length=lv;

}

Rectangle(Rectangle&rr):

Point(rr){

width=rr.width;

length=rr.length;

}

doubleArea(){returnwidth*length;}

voidShow(){

cout<<"x="<

}

intposition(Point&pt);

};

intRectangle:

:

position(Point&pt){

doubles1,s2;

s1=(pt.getx()-getx());s2=(pt.gety()-gety());

if(((s1==0||s1==width)&&s2<=length)||((s2==0||s2==length)&&s1<=width))return0;

elseif(s1

elsereturn1;//1在矩形外

}

intmain(){

Circlecc1(3,4,5),cc2,cc3(cc1);

Rectanglert1(0,0,6,8),rt2,rt3(rt1);

Pointp1(0,0),p2(6,8),p3(3,3),p4(8,4),p5(8,8);

cc1.Show();

cc2.Show();

rt1.Show();

rt2.Show();

cout<<"点p1:

";

p1.Show();

cout<<"矩形rt3:

"<<'\t';

rt3.Show();

switch(rt3.position(p1)){

case0:

cout<<"在矩形上"<

case-1:

cout<<"在矩形内"<

case1:

cout<<"在矩形外"<

}

cout<<"圆cc3:

"<<'\t';

cc3.Show();

switch(cc3.position(p1)){

case0:

cout<<"在圆上"<

case-1:

cout<<"在圆内"<

case1:

cout<<"在圆外"<

}

cout<<"点p2:

";

p2.Show();

cout<<"矩形rt3:

"<<'\t';

rt3.Show();

switch(rt3.position(p2)){

case0:

cout<<"在矩形上"<

case-1:

cout<<"在矩形内"<

case1:

cout<<"在矩形外"<

}

cout<<"圆cc3:

"<<'\t';

cc3.Show();

switch(cc3.position(p2)){

case0:

cout<<"在圆上"<

case-1:

cout<<"在圆内"<

case1:

cout<<"在圆外"<

}

cout<<"点p3:

";

p3.Show();

cout<<"矩形rt3:

"<<'\t';

rt3.Show();

switch(rt3.position(p3)){

case0:

cout<<"在矩形上"<

case-1:

cout<<"在矩形内"<

case1:

cout<<"在矩形外"<

}

cout<<"圆cc3:

"<<'\t';

cc3.Show();

switch(cc3.position(p3)){

case0:

cout<<"在圆上"<

case-1:

cout<<"在圆内"<

case1:

cout<<"在圆外"<

}

cout<<"点p4:

";

p4.Show();

cout<<"矩形rt3:

"<<'\t';

rt3.Show();

switch(rt3.position(p4)){

case0:

cout<<"在矩形上"<

case-1:

cout<<"在矩形内"<

case1:

cout<<"在矩形外"<

}

cout<<"圆cc3:

"<<'\t';

cc3.Show();

switch(cc3.position(p4)){

case0:

cout<<"在圆上"<

case-1:

cout<<"在圆内"<

case1:

cout<<"在圆外"<

}

cout<<"点p5:

";

p5.Show();

cout<<"矩形rt3:

"<<'\t';

rt3.Show();

switch(rt3.position(p5)){

case0:

cout<<"在矩形上"<

case-1:

cout<<"在矩形内"<

case1:

cout<<"在矩形外"<

}

cout<<"圆cc3:

"<<'\t';

cc3.Show();

switch(cc3.position(p5)){

case0:

cout<<"在圆上"<

case-1:

cout<<"在圆内"<

case1:

cout<<"在圆外"<

}

return0;

}

8.6几何形体的派生关系如下:

对平面形体有长和面积,对立体有表面积和体积,对几何图形基类,周长、面积和体积应怎样计算(用什么函数)?

对平面图形体积怎样计算(用什么函数)?

对立体图形周长怎么计算(用什么函数)?

要求实现运行时的多态性。

请编程,并测试。

解:

运行时的多态性要用指针

#include

#include

usingnamespacestd;

constdoublePI=3.35;

classGeometric_shape{//几何图形

public:

virtualdoubleperimeter()=0;//周长

virtualdoublearea()=0;//面积

virtualdoublevolume()=0;//体积

virtualvoidShow(){};

};

classCircle:

publicGeometric_shape{//圆

doubleradius;

public:

Circle(){radius=0;}

Circle(doublevv){radius=vv;}

doubleperimeter(){return2.0*PI*radius;}//周长

doublearea(){returnPI*radius*radius;}//面积

doublevolume(){return0;}//体积

voidShow(){cout<<"radius="<

};

classRectangle:

publicGeometric_shape{//矩形

doublewidth,length;

public:

Rectangle(){width=0;length=0;}//长宽

Rectangle(doublewid,doublelen){

width=wid;

length=len;

}

Rectangle(Rectangle&rr){

width=

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 解决方案 > 其它

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1