第四版课后习题答案第08章 多态性.docx
《第四版课后习题答案第08章 多态性.docx》由会员分享,可在线阅读,更多相关《第四版课后习题答案第08章 多态性.docx(18页珍藏版)》请在冰点文库上搜索。
![第四版课后习题答案第08章 多态性.docx](https://file1.bingdoc.com/fileroot1/2023-7/23/fc4c1571-7aad-4e0a-a1ae-1b9f89a99332/fc4c1571-7aad-4e0a-a1ae-1b9f89a993321.gif)
第四版课后习题答案第08章多态性
第八章多态性
8-1什么叫做多态性?
在C++中是如何实现多态的?
解:
多态是指同样的消息被不同类型的对象接收时导致完全不同的行为,是对类的特定成员函数的再抽象。
C++支持的多态有多种类型,重载(包括函数重载和运算符重载)和虚函数是其中主要的方式。
8-2什么叫做抽象类?
抽象类有何作用?
抽象类的派生类是否一定要给出纯虚函数的实现?
解:
带有纯虚函数的类是抽象类。
抽象类的主要作用是通过它为一个类族建立一个公共的接口,使它们能够更有效地发挥多态特性。
抽象类声明了一组派生类共同操作接口的通用语义,而接口的完整实现,即纯虚函数的函数体,要由派生类自己给出。
但抽象类的派生类并非一定要给出纯虚函数的实现,如果派生类没有给出纯虚函数的实现,这个派生类仍然是一个抽象类。
8-3声明一个参数为整型,无返回值,名为fn1的虚函数。
解:
virtualvoidfn1(int);
8-4在C++中,能否声明虚构造函数?
为什么?
能否声明虚析构函数?
有何用途?
解:
在C++中,不能声明虚构造函数,多态是不同的对象对同一消息有不同的行为特性,虚函数作为运行过程中多态的基础,主要是针对对象的,而构造函数是在对象产生之前运行的,因此虚构造函数是没有意义的;可以声明虚析构函数,析构函数的功能是在该类对象消亡之前进行一些必要的清理工作,如果一个类的析构函数是虚函数,那么,由它派生而来的所有子类的析构函数也是虚函数。
析构函数设置为虚函数之后,在使用指针引用时可以动态联编,实现运行时的多态,保证使用基类的指针就能够调用适当的析构函数针对不同的对象进行清理工作。
8-5实现重载函数Double(x),返回值为输入参数的两倍;参数分别为整型、长整型、浮点型、双精度型,返回值类型与参数一样。
解:
源程序:
#include
intDouble(int);
longDouble(long);
floatDouble(float);
doubleDouble(double);
intmain()
{
intmyInt=6500;
longmyLong=65000;
floatmyFloat=6.5F;
doublemyDouble=6.5e20;
intdoubledInt;
longdoubledLong;
floatdoubledFloat;
doubledoubledDouble;
cout<<"myInt:
"<cout<<"myLong:
"<cout<<"myFloat:
"<cout<<"myDouble:
"<doubledInt=Double(myInt);
doubledLong=Double(myLong);
doubledFloat=Double(myFloat);
doubledDouble=Double(myDouble);
cout<<"doubledInt:
"<cout<<"doubledLong:
"<cout<<"doubledFloat:
"<cout<<"doubledDouble:
"<return0;
}
intDouble(intoriginal)
{
cout<<"InDouble(int)\n";
return2*original;
}
longDouble(longoriginal)
{
cout<<"InDouble(long)\n";
return2*original;
}
floatDouble(floatoriginal)
{
cout<<"InDouble(float)\n";
return2*original;
}
doubleDouble(doubleoriginal)
{
cout<<"InDouble(double)\n";
return2*original;
}
程序运行输出:
myInt:
6500
myLong:
65000
myFloat:
6.5
myDouble:
6.5e+20
InDouble(int)
InDouble(long)
InDouble(float)
InDouble(double)
DoubledInt:
13000
DoubledLong:
130000
DoubledFloat:
13
DoubledDouble:
1.3e+21
8-6定义一个Rectangle类,有长itsWidth、宽itsLength等属性,重载其构造函数Rectangle()和Rectangle(int
width,intlength)。
解:
源程序:
#include
classRectangle
{
public:
Rectangle();
Rectangle(intwidth,intlength);
~Rectangle(){}
intGetWidth()const{returnitsWidth;}
intGetLength()const{returnitsLength;}
private:
intitsWidth;
intitsLength;
};
Rectangle:
:
Rectangle()
{
itsWidth=5;
itsLength=10;
}
Rectangle:
:
Rectangle(intwidth,intlength)
{
itsWidth=width;
itsLength=length;
}
intmain()
{
RectangleRect1;
cout<<"Rect1width:
"<cout<<"Rect1length:
"<intaWidth,aLength;
cout<<"Enterawidth:
";
cin>>aWidth;
cout<<"\nEnteralength:
";
cin>>aLength;
RectangleRect2(aWidth,aLength);
cout<<"\nRect2width:
"<cout<<"Rect2length:
"<return0;
}
程序运行输出:
Rect1width:
5
Rect1length:
10
Enterawidth:
20
Enteralength:
50
Rect2width:
20
Rect2length:
50
8-7定义计数器Counter类,对其重载运算符+。
解:
源程序:
typedefunsignedshortUSHORT;
#include
classCounter
{
public:
Counter();
Counter(USHORTinitialValue);
~Counter(){}
USHORTGetItsVal()const{returnitsVal;}
voidSetItsVal(USHORTx){itsVal=x;}
Counteroperator+(constCounter&);
private:
USHORTitsVal;
};
Counter:
:
Counter(USHORTinitialValue):
itsVal(initialValue)
{
}
Counter:
:
Counter():
itsVal(0)
{
}
CounterCounter:
:
operator+(constCounter&rhs)
{
returnCounter(itsVal+rhs.GetItsVal());
}
intmain()
{
CountervarOne
(2),varTwo(4),varThree;
varThree=varOne+varTwo;
cout<<"varOne:
"<cout<<"varTwo:
"<cout<<"varThree:
"<return0;
}
程序运行输出:
varOne:
2
varTwo:
4
varThree:
6
8-5定义一个哺乳动物Mammal类,再由此派生出狗Dog类,二者都定义Speak()成员函数,基类中定义为虚函数,定义一个Dog类的对象,调用Speak函数,观察运行结果。
解:
源程序:
#include
classMammal
{
public:
Mammal(){cout<<"Mammalconstructor...\n";}
~Mammal(){cout<<"Mammaldestructor...\n";}
virtualvoidSpeak()const{cout<<"Mammalspeak!
\n";}
};
classDog:
publicMammal
{
public:
Dog(){cout<<"DogConstructor...\n";}
~Dog(){cout<<"Dogdestructor...\n";}
voidSpeak()const{cout<<"Woof!
\n";}
};
intmain()
{
Mammal*pDog=newDog;
pDog->Speak();
return0;
}
程序运行输出:
Mammalconstructor...
Dogconstructor...
Woof!
Dogdestructor...
Mammaldestructor...
8-6
定义一个Shape抽象类,在此基础上派生出Rectangle和Circle,二者都有GetArea()函数计算对象的面积,GetPerim()函数计算对象的周长。
解:
源程序:
#include
classShape
{
public:
Shape(){}
~Shape(){}
virtualfloatGetArea()=0;
virtualfloatGetPerim()=0;
};
classCircle:
publicShape
{
public:
Circle(floatradius):
itsRadius(radius){}
~Circle(){}
floatGetArea(){return3.14*itsRadius*itsRadius;}
floatGetPerim(){return6.28*itsRadius;}
private:
floatitsRadius;
};
classRectangle:
publicShape
{
public:
Rectangle(floatlen,floatwidth):
itsLength(len),itsWidth(width){};
~Rectangle(){};
virtualfloatGetArea(){returnitsLength*itsWidth;}
floatGetPerim(){return2*itsLength+2*itsWidth;}
virtualfloatGetLength(){returnitsLength;}
virtualfloatGetWidth(){returnitsWidth;}
private:
floatitsWidth;
floatitsLength;
};
voidmain()
{
Shape*sp;
sp=newCircle(5);
cout<<"TheareaoftheCircleis"<GetArea()<cout<<"TheperimeteroftheCircleis"<GetPerim()<deletesp;
sp=newRectangle(4,6);
cout<<"TheareaoftheRectangleis"<GetArea()<cout<<"TheperimeteroftheRectangleis"<GetPerim()<deletesp;
}
程序运行输出:
TheareaoftheCircleis78.5
TheperimeteroftheCircleis31.4
TheareaoftheRectangleis24
TheperimeteroftheRectangleis20
8-7对Point类重载++(自增)、--(自减)运算符
解:
#include
classPoint
{
public:
Point&operator++();
Pointoperator++(int);
Point&operator--();
Pointoperator--(int);
Point(){_x=_y=0;}
intx(){return_x;}
inty(){return_y;}
private:
int_x,_y;
};
Point&Point:
:
operator++()
{
_x++;
_y++;
return*this;
}
PointPoint:
:
operator++(int)
{
Pointtemp=*this;
++*this;
returntemp;
}
Point&Point:
:
operator--()
{
_x--;
_y--;
return*this;
}
PointPoint:
:
operator--(int)
{
Pointtemp=*this;
--*this;
returntemp;
}
voidmain()
{
PointA;
cout<<"A的值为:
"<A++;
cout<<"A的值为:
"<++A;
cout<<"A的值为:
"<A--;
cout<<"A的值为:
"<--A;
cout<<"A的值为:
"<}
程序运行输出:
A的值为:
0,0
A的值为:
1,1
A的值为:
2,2
A的值为:
1,1
A的值为:
0,0
8-8
定义一个基类BaseClass,从它派生出类DerivedClass,BaseClass有成员函数fn1()、fn2(),fn1()是虚函数,DerivedClass也有成员函数fn1()、fn2(),在主程序中定义一个DerivedClass的对象,分别用BaseClass和DerivedClass的指针来调用fn1()、fn2(),观察运行结果。
解:
#include
classBaseClass
{
public:
virtualvoidfn1();
voidfn2();
};
voidBaseClass:
:
fn1()
{
cout<<"调用基类的虚函数fn1()"<}
voidBaseClass:
:
fn2()
{
cout<<"调用基类的非虚函数fn2()"<}
classDerivedClass:
publicBaseClass
{
public:
voidfn1();
voidfn2();
};
voidDerivedClass:
:
fn1()
{
cout<<"调用派生类的函数fn1()"<}
voidDerivedClass:
:
fn2()
{
cout<<"调用派生类的函数fn2()"<}
voidmain()
{
DerivedClassaDerivedClass;
DerivedClass*pDerivedClass=&aDerivedClass;
BaseClass*pBaseClass=&aDerivedClass;
pBaseClass->fn1();
pBaseClass->fn2();
pDerivedClass->fn1();
pDerivedClass->fn2();
}
程序运行输出:
调用派生类的函数fn1()
调用基类的非虚函数fn2()
调用派生类的函数fn1()
调用派生类的函数fn2()
8-9
定义一个基类BaseClass,从它派生出类DerivedClass,BaseClass中定义虚析构函数,在主程序中将一个DerivedClass的对象地址赋给一个BaseClass的指针,观察运行过程。
解:
#include
classBaseClass{
public:
virtual~BaseClass(){
cout<<"~BaseClass()"<}
};
classDerivedClass:
publicBaseClass{
public:
~DerivedClass(){
cout<<"~DerivedClass()"<}
};
voidmain()
{
BaseClass*bp=newDerivedClass;
deletebp;
}
程序运行输出:
~DerivedClass()
~BaseClass()
8-10定义Point类,有成员变量X、Y,为其定义友元函数实现重载+。
解:
#include
classPoint
{
public:
Point(){X=Y=0;}
Point(unsignedx,unsignedy){X=x;Y=y;}
unsignedx(){returnX;}
unsignedy(){returnY;}
voidPrint(){cout<<"Point("<friendPointoperator+(Point&pt,intnOffset);
friendPointoperator+(intnOffset,Point&pt);
private:
unsignedX;
unsignedY;
};
Pointoperator+(Point&pt,intnOffset)
{
PointptTemp=pt;
ptTemp.X+=nOffset;
ptTemp.Y+=nOffset;
returnptTemp;
}
Pointoperator+(intnOffset,Point&pt)
{
PointptTemp=pt;
ptTemp.X+=nOffset;
ptTemp.Y+=nOffset;
returnptTemp;
}
voidmain()
{
Pointpt(10,10);
pt.Print();
pt=pt+5;//Point+int
pt.Print();
pt=10+pt;//int+Point
pt.Print();
}
程序运行输出:
Point(10,10)
Point(15,15)
Point(25,25)