8C第八章习题解答文档格式.docx
《8C第八章习题解答文档格式.docx》由会员分享,可在线阅读,更多相关《8C第八章习题解答文档格式.docx(45页珍藏版)》请在冰点文库上搜索。
![8C第八章习题解答文档格式.docx](https://file1.bingdoc.com/fileroot1/2023-5/5/a4b63589-59da-45fa-be92-187d6ef04f27/a4b63589-59da-45fa-be92-187d6ef04f271.gif)
除了非成员函数不能作为虚函数外,(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访问限定符基类类名{...};
访问限定符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<
iostream>
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{//鞋子类
classAir_Cindition:
publicElectric_Appliance{//空调
boolwarm_cool;
//是否冷暖
floatpower;
//功率
classTelevision:
publicElectric_Appliance{//电视类
intSize;
//尺寸
boolisColor;
//是否彩色
classAcoustics:
publicElectric_Appliance{//音响类
intspeaker_num;
//喇叭数目
//功率
classBicycle:
publicVehicle{//自行车类
intspeed_grades;
//调速级数
intwheel_size;
//轮子大小
classCar:
publicVehicle{//轿车类
floatvolume;
//排气量
boolisSkylight;
//是否有天窗
intbox_num;
//厢数
classMotorcycle:
publicVehicle{//摩托车类
intmain(){
return0;
}
8.5以点(point)类为基类,重新定义矩形类和圆类。
点为直角坐标点,矩形水平放置,由左下方的顶点和长宽定义。
圆由圆心和半径定义。
派生类操作判断任一坐标点是在图形内,还是在图形的边缘上,还是在图形外。
缺省初始化图形退化为点。
要求包括拷贝构造函数。
编程测试类设计是否正确。
cmath>
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="
x<
'
'
y="
y<
endl;
classCircle:
publicPoint{
doubleradius;
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<
getx()<
\t'
gety()<
radius="
radius<
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:
doublewidth,length;
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(){
;
width="
width<
length="
length<
pt);
intRectangle:
:
position(Point&
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<
width&
length)return-1;
//0在矩形上,-1在矩形内
elsereturn1;
//1在矩形外
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();
矩形rt3:
rt3.Show();
switch(rt3.position(p1)){
case0:
cout<
在矩形上"
break;
case-1:
在矩形内"
case1:
在矩形外"
圆cc3:
cc3.Show();
switch(cc3.position(p1)){
在圆上"
在圆内"
在圆外"
点p2:
p2.Show();
switch(rt3.position(p2)){
switch(cc3.position(p2)){
点p3:
p3.Show();
switch(rt3.position(p3)){
switch(cc3.position(p3)){
点p4:
p4.Show();
switch(rt3.position(p4)){
switch(cc3.position(p4)){
点p5:
p5.Show();
switch(rt3.position(p5)){
switch(cc3.position(p5)){
8.6几何形体的派生关系如下:
对平面形体有长和面积,对立体有表面积和体积,对几何图形基类,周长、面积和体积应怎样计算(用什么函数)?
对平面图形体积怎样计算(用什么函数)?
对立体图形周长怎么计算(用什么函数)?
要求实现运行时的多态性。
请编程,并测试。
运行时的多态性要用指针
classGeometric_shape{//几何图形
virtualdoubleperimeter()=0;
//周长
virtualdoublearea()=0;
//面积
virtualdoublevolume()=0;
//体积
virtualvoidShow(){};
publicGeometric_shape{//圆
Circle(doublevv){radius=vv;
doubleperimeter(){return2.0*PI*radius;
}//周长
doublearea(){returnPI*radius*radius;
}//面积
doublevolume(){return0;
}//体积
publicGeometric_shape{//矩形
}//长宽
Rectangle(doublewid,doublelen){
width=wid;
length=len;
rr){
width=