C++网络作业6答案Word下载.docx
《C++网络作业6答案Word下载.docx》由会员分享,可在线阅读,更多相关《C++网络作业6答案Word下载.docx(28页珍藏版)》请在冰豆网上搜索。
(<
参数表>
)
4对虚函数的调用________。
A)一定使用动态联编B)必须使用动态联编
C)一定使用静态联编D)不一定使用动态联编
参见第1题的注释。
5实现运行时的多态性要使用___________。
A)重载函数B)构造函数C)析构函数D)虚函数
6要实现动态联编,必须通过____调用虚函数。
A)对象指针B)成员名限定C)对象名D)派生类名
7在派生类中重新定义虚函数时,除了_____方面,其他方面都必须与基类中相应的
虚函数保持一致。
A)参数个数B)参数类型C)函数名称D)函数体
参见第2题的注释。
8下面关于构造函数和析构函数的描述,错误的是__。
A)析构函数中调用虚函数采用静态联编
B)对虚析构函数的调用可以采用动态联编
C)当基类的析构函数是虚函数时,其派生类的析构函数也一定是虚函数
D)构造函数可以声明为虚函数
构造函数不能声明为虚函数,但析构函数可以声明为虚函数。
当基类的析构函
数声明为虚函数时,无论派生类是否使用virtual关键字说明,派生类的析构函数一定
是虚函数,对缺省析构函数亦然。
而且,如果满足动态联编的其他条件,对虚析构函
数的调用将采用动态联编。
构造函数不能声明为虚函数,但在构造函数中可以调用虚函数。
在构造函数或析
构函数中调用虚函数,将采用静态联编。
9关于纯虚函数和抽象类的描述中,错误的是__。
C
A)纯虚函数是一种特殊的虚函数,它没有具体的实现
B)抽象类是指具有纯虚函数的类
C)一个基类中说明有纯虚函数,该基类的派生类一定不再是抽象类
D)抽象类只能作为基类来使用,其纯虚函数的实现由派生类给出
带有纯虚函数的类称为抽象类。
抽象类中的纯虚函数的实现由派生类给出:
但派生类仍可不给出纯虚函数的定义,继续作为抽象类存在。
10下列描述中,____是抽象类的特性。
A)可以说明虚函数B)可以进行构造函数重载
C)可以定义友元函数D)不能说明其对象
抽象类区别于其他类的最根本的特征是不能定义对象。
11_______是一个在基类中说明的虚函数,它在该基类中没有定义,但要求任何派生
类都必须定义自己的版本。
C
A)虚析构函数B)虚构造函数C)纯虚函数D)静态成员函数
12如果一个类至少有一个纯虚函数,那么就称该类为__。
A)抽象类B)虚基类C)派生类D)以上都不对
13以下___成员函数表示纯虚函数。
A)virtualintvf(int);
B)voidvf(int)=0;
C)virtualvoidvf()=0;
D)virtualvoidvf(int)()
纯虚函数的声明格式如下:
virtual<
)=0;
注意纯虚函数与虚函数体为空的区别。
纯虚函数根本就没有函数体,而空的虚
函数的函数体为空:
前者所在的类是抽象类,不能直接进行实例化,而后者所在的
类是可以实例化的:
14下面的描述中,正确的是_____。
A)virtual可以用来声明虚函数
B)含有纯虚函数的类是不可以用来创建对象的,因为它是虚基类
C)即使基类的构造函数没有参数,派生类也必须建立构造函数
D)静态数据成员可以通过成员初始化列表来初始化
virtual关键字既可以用来声明虚基类,也可以用来声明虚函数。
含有纯虚函数的类是抽象类,它不能用来定义对象。
静态数据成员的初始化必须在类体外进行。
如果所有的基类和子对象构造函数都不需要参数,派生类也不需要参数时,派
生类构造函数可以不定义。
15在下面程序中,A、B、C、D四句编译时不会出现错误的是__。
#include<
iostream.h>
classBase
{
public:
Base(){}
Base(intc):
count(c){}
virtualvoidprint()const=0;
private:
intcount;
};
classDerived:
publicBase
public:
Derived():
Base(0){}
Derived(intc):
Base(c){}
voidprint()const{cout<
"
Derived"
endl;
}
voidmain()
Derivedd(10);
Base*pb;
pb=&
d;
//A
Base&
cb=d;
Deriveddd=*pb;
Derived&
cd=cb;
//C
Basebb=d;
//D
}
B和C处不符合赋值兼容规则。
D处出错是因为Base是含有纯虚函数的抽象
类,不能建立抽象类的对象。
16在下面程序中,A,B、C、D四句编译时出现错误的是___。
classA//A
{
//B
A(){func();
}//C
virtualvoidfunc()=0;
构造函数中不能调用纯虚函数,但可以调用虚函数。
17分析下面的程序,正确的输出结果是___B
#include<
string.h>
virtualchar*fun()const=0;
char*Base:
:
fun()const{return“Base”;
classDerivedl1:
virtualpublicBase
char*fun()const{return"
Derived11"
;
classDerivedl2:
char*fun()const{return"
Derivedl2"
classDerived2:
publicDerivedl1,publicDerivedl2
char*fun()const
{
char*ptr;
ptr=newchar[strlen(Derivedl1:
fun())+strlen(Derivedl2:
fun())+l];
strcpy(ptr,Derived11:
fun()),
strcat(ptr,Derived12:
fun());
returnptr;
}
Base*pb;
pb=newDerived11;
cout<
pb->
fun()<
pb=newDerivedl2;
pb=newDerived2;
A)B)
BaseDerivedl1
BaseDerivedl2
BaseDerivedl1Derivedl2
C)D)
Derivedl1Derivedl2
Derivedl1Derivedl2Derivedl1Derivedl2
参见第1题、第2题的注释。
派生类Derivedll、Derivedl2和Derived2中的
函数fun与基类Base中的虚函数fun的函数名、参数表和返回类型都完全相同,因
此这三个类中的fun函数也是虚函数,对fun函数的调用采用动态联编。
二、填空题
1动态联编中直到_①程序运行_时才能确定调用哪个函数;
而静态联编则是在_②程序编译时进行的。
注释:
动态联编与静态联编的概念。
2静态联编所支持的多态性称为_①编译时的_多态性,动态联编所支持的多态性则称为
__②运行时的__多态性,动态多态性由_③虚函数____来支持。
在C++中,多态性的实现和联编有关。
3对虚函数使用对象指针或引用调用,系统使用__①动态__联编;
使用对象调用时.
系统使用__②静态__联编。
参见选择填空第1题、第5题的注释。
4动态联编是在__①虚函数___的支持下实现的,它通过_②指针或引用来调用该函数操作。
5在一个成员函数内调用一个虚函数时,对该虚函数的调用进行__动态_____联编。
6在析构函数中调用虚函数时,采用___静态_____联编。
7C++中__①不支持___虚构造函数,但___②支持___虚析构函数。
参见选择填空第8题的注释。
多态是不同的对象对同一消息有不同的行为特征,虚函数作为运行过程中多态的基础,主要是针对对象的,而构造函数的调用意味着要建立一个对象,这时必须确切地知道这个对象的类型,并且,我们也不会为一个已存在的对象调用构造函数。
因此,虚构造函数没有意义。
在C++中可以声明虚析构函数。
析构函数的功能是在该类对象消亡之前进行一些必要的清理工作,如果一个类的析构函数是虚函数,那么,由它派生而来的所有子类的析构函数也是虚函数。
析构函数设置为虚函数后,在使用指针调用时可以进行动态联编,实现运行时的多态,从而保证使用基类的指针就能够调用适当的析构函数针对不同的对象进行清理工作。
8在类定义中,将__=0__置于虚函数的函数原型的末尾可以将该函数声明为纯虚函数
9带有_①纯虚函数_的类称为抽象类,它只能作为_②基类_来使用。
抽象类的作用主要有两个:
直接用作基类或用作指针或引用的基类型。
10抽象类不能__①定义对象__,但可以__②声明抽象类的指针或引用__作为参数类型,函数返回类型或显式转换类型。
注意抽象类不能定义对象是指不能定义需要分配存储空间的对象。
因此可以
声明抽象类的指针或引用,它们在程序运行时可以指向并访问派生类对象。
11下列程序的运行结果如下:
Derivel'
sPrint()called.
Derive2'
根据结果将程序补充完整。
classBase
Base(inti){b=i;
___①virtualvoidPrint()=0;
___
protected:
intb;
classDerivel:
publicBase
___②Derive1(inti):
Base(i){}___
voidPrint()
{
cout<
”Derive1’sPrint()called.”<
}
classDerive2:
_③public:
Derive1(inti):
Base(i){}
voidPrint(){cout<
”Derive2’sPrint()called.“<
endl;
}_____
voidfun(_④Base*obj__)
obj->
Print();
_⑤Derive1*d1=newDerive1
(1);
_
Derive2*d2=newDerive2
(2);
fun(dl);
fun(d2);
派生类Derived1和Derived2从基类Base公有继承,它们是Base的子类型。
主程序中两次调用fun函数,该函数通过指针对象obj调用了Print函数,得到
了不同的输出结果。
而同样的消息被不同类型的对象接收时导致完全不同的行为,
恰好体现了面向对象的多态特性。
根据运行时的多态必须满足的条件,Print函数一
定是一个虚函数,并且在所有类中都必须进行定义。
由于Base类中的Print函数除
了提供一个公共的接口外,没有其他的作用,所以最好定义为纯虚函数。
12将下列程序补充完整。
classconvert
convert(doublei){vail=i;
_①virtualvoidcompute()=0;
doubleval1;
doubleval2;
//literstogallons
classl_to_g:
publicconvert
__②l_to_g(doublei):
convert(i){}_
voidcompute()
val2=val1/3.7854;
cout<
val1<
litersis"
val2<
gallons."
};
//FahrenheittoCelsius
classf_to_c:
f_to_c(doublei):
convert(i){}
voidcompute()
{
val2=(val1-32)*5/9;
cout<
val1<
”Fahrenheitis“<
”Celsius.”<
voidfun(__④convert&
f_)
pute();
l_to_glgobj(4);
f_to_cfcobj(70);
fun(lgobj);
fun(fcobj);
13根据不同的输出结果,在函数Tone中填入正确的语句。
classInstrument
virtualvoidPrint()const{cout<
Instrument:
Print"
classPiano:
publicInstrument
voidPrint()const{cout<
Piano:
classGuitar:
voidPrint()const{cout<
Guitar:
voidTone(_____①_____)
___②_____
Guitarg;
Tone(g);
Pianop;
Tone(p);
(1)输出结果为:
:
Print
Instmment:
(2)输出结果为:
(1)①Instrumentobj②obj.Print()
(2)①Instrument&
obj②obj.Print()
参考第3题,第一次的输出是由静态联编产生的,第二次的输出是由动态态联编产生的。
14下列程序的运行结果如下:
Base'
scons.
Derived'
sdes.
Base(){cout<
scons."
_①virtual~Base()_{cout<
sdes."
Derived(){cout<
~Derived(){cout<
Base*ptr=_____②newDerived______
deleteptr;
三、编程
1.在作业1编程1的Point类中完成赋值运算符=、插入运算符<
、比较运算符==、!
=和加法运算符+、-的重载。
math.h>
classPoint
{public:
Point(floatx=0,floaty=0,floatz=0):
x_(x),y_(y),z_(z){}
Point(constPoint&
p):
x_(p.x_),y_(p.y_),z_(p.z_){}
//形参point为常引用,它所引用的对象不能被更新,即传给它的实参不能被更新。
voidnegate(){x_*=-1;
y_*=-1;
z_*=-1;
doublenorm(){returnsqrt(x_*x_+y_*y_+z_*z_);
voidprint()
{cout<
'
('
<
x_<
"
"
y_<
z_<
)"
Point&
operator=(constPoint&
point);
boolPoint:
operator==(constPoint&
point)const
//常成员函数,只有它才有资格操作常量和常对象
{returnx_==point.x_&
&
y_==point.y_&
z_==point.z_;
operator!
=(constPoint&
point)const
{returnx_!
=point.x_||y_!
=point.y_||z_!
=point.z_;
friendPointoperator+(constPoint&
p1,constPoint&
p2);
friendPointoperator-(constPoint&
friendostream&
operator<
(ostream&
ostr,constPoint&
private:
floatx_,y_,z_;
Pointoperator+(constPoint&
p2)
{returnPoint(p1.x_+p2.x_,p1.y_+p2.y_,p1.z_+p2.z_);
Pointoperator-(constPoint&
{returnPoint(p1.x_-p2.x_,p1.y_-p2.y_,p1.z_-p2.z_);
ostream&
point)
{returnostr<
("
point.x_<
point.y_<
point.z_<
Point&
Point:
operator=(constPoint&
{x_=point.x_;
y_=point.y_;
z_=point.z_;
return*this;
{Pointp(12,-3,4),q(14,5,12),r1,r2;
r1=p+q;
cout<
r1<
r1.norm()<
r2=p-q+r1;
cout<
r2<
r2.norm()<
if(r1==r2)cout<
r1==r2"
elsecout<
r1!
=r2"
2.假设Point类的坐标为整型,对它重载++(自增)、--(自减)运算符(包括前后缀)。
Point(intx=0,inty=0,intz=0):
Point(constPoint&
x_(p.x_),y_(p.y_),z_(p.z_){