面向对象程序设计习题Word下载.docx
- 文档编号:21002775
- 上传时间:2023-01-26
- 格式:DOCX
- 页数:32
- 大小:33.07KB
面向对象程序设计习题Word下载.docx
《面向对象程序设计习题Word下载.docx》由会员分享,可在线阅读,更多相关《面向对象程序设计习题Word下载.docx(32页珍藏版)》请在冰豆网上搜索。
C
A.指向A的指针为a
B.将变量a的地址赋给类A
C.类A对象引用a用作函数的形参
D.变量A与a按位与后作函数参数
[解析]因为A是一个类,所以“A&
a”表示a是类A的对象,但因为对象a的前缀了符号“&
”,则“&
a”表示是类A的对象引用。
所以“A&
a”的含义是类A对象引用a用作函数的形参。
6.若类A和类B的定义如下:
classA{
public:
inti,j;
voidget();
};
classB:
A{
inti,j;
protected:
intk;
voidmake();
voidB:
:
make(){k=i*j;
}
则其中()是非法的表达式。
参考答案为:
D
A.voidget();
B.intk;
C.voidmake();
D.k=i*j;
[解析]对于给定的四项中,前三项都是正确的,只有第四项是错误的。
因为,类B是类A的私有派生类(缺省访问类型),所以A中的公类型的数据成员在类B中成为了私有数据成员,但函数“voidB:
make()”既然是类B的成员函数,则既可访问类A中的公有数据成员,也能访问类B中的私有数据成员,则表达式“k=i*j;
”造成了访问的二义性,即其中的i和j,到底是取自类A呢?
还是取自类B呢?
7.下面的主程序中,语句()是错误的。
classA{
inti;
virtualvoidfun()=0;
A(inta){i=a;
};
classB{
intj;
voidfun(){cout<
<
”B:
fun()\n”;
B(intb,intc):
A(b){j=c;
voidmain() 参考答案为:
A.{Aa(5);
B.A*pa;
C.Bb(7);
D.B*pb;
}
[解析]在类A中,函数“virtualvoidfun()=0”为纯虚函数,因此,类A为抽象类。
作为抽象类,它是不能被用来定义具体对象的,而语句“Aa(5);
”恰恰是定义抽象类的对象的,所以它是错误的
8.拷贝(复制)构造函数的作用是 参考答案为:
A.进行数据类型的转换
B.用对象调用成员函数
C.用对象初始化对象
D.用一般类型的数据初始化对象
[解析]进行数据类型的转换和用一般类型的数据初始化对象都是一般构造函数的功能。
用对象调用成员函数不用构造函数,只要用“对象名.成员函数名”即可。
所以拷贝(复制)构造函数的作用,只能是用对象来初始化对象。
9.下列说法中,正确的说法是 参考答案为:
B
A.所有的运算符都能被重载
B.运算符被重载时,它们的优先级与结合性不会改变
C.当需要时,我们可以自定义一个运算符来进行重载
D.每个运算符都可以被重载成成员函数和友元函数
[解析]当重载运算符时,不是所有的运算符都能被重载,有几个运算符是不能被重载的,如三元运算符“?
:
”、‘.’、‘*’、‘:
’、‘#’等;
也不是每个运算符都可以被重载成成员函数和友元函数,如运算符‘=’、‘()’、‘[]’、和‘→’都只能被重载成成员函数;
无论何时,都不能自定义运算符来进行重载,也即重载只能对已有运算符进行;
但是运算符被重载时,它们的优先级与结合性不会改变。
10.下面对结构或类中成员的访问中,不正确的访问是 参考答案为:
A.*pointer.salary;
(其中pointer为指向类对象的指针)
B.pointer->
salary;
C.x=worker.salary;
(其中worker为具有类类型的对象)
D.Location&
rA=A1;
intx=rA.GetX();
(Location为已定义的类,A1为对象)
[解析]因pointer为指向类对象的指针,所以“pointer->
salary”是正确的访问数据成员的形式;
因worker为具有类类型的对象,所以“worker.salary”也是正确的访问数据成员的形式;
因Location为已定义的类,A1为对象,所以“Location&
”表示以对象A1初始化对象引用rA,然后由对象引用rA调用成员函数GetX()给变量x赋值,这样的访问成员函数的形式也是正确的;
“*pointer.salary;
”中,因为运算符‘.’的优先级高于运算符‘*’的优先级,所以相当于“*(pointer.salary);
”,那正确的形式应该是“*(pointer→salary);
”。
故“*pointer.salary”是不正确的访问。
11.C++对C语言作了很多改进,即从面向过程变成为面向对象的主要原因是()D
A.增加了一些新的运算符B.允许函数重载,并允许设置缺省参数C.规定函数说明符必须用原型D.引进了类和对象的概念
12.下列符号不能组成标识符的是(A)A.连接符B.下划线C.大小写字母D.数字字符
13.类型修饰符unsigned不能修饰(D)A.charB.intC.longintD.float
14.在inta=3,int*p=&
a;
中,*p的值是(D)A.变量a的地址值B.无意义C.变量p的地址值D.3
15.下列关于指针的操作中,错误的是(D)A.两个同类型的指针可以进行比较运算B.可以用一个空指针赋给某个指针C.一个指针可以加上两个整数之差D.两个同类型的指针可以相加
二,填空题 不写解答过程,将正确的答案写在每小题的空格内。
错填或不填均无分。
1.面向对象程序设计中的多态性包括静态多态性和动态多态性,前者由____________机制支持,而后者则由____________机制支持。
答:
函数重载、虚函数
[解析]静态多态性又称编译时多态性,调用何函数应该在编译之前就知道了,所以必须由函数重载机制来支持。
动态多态性又称运行时多态性,调用何函数只有在运行时才知道,所以由虚函数(与指针或引用)机制来支持。
2.由charconst*str=”stucture”;
所以定义的指针称为____________,关键字const所修饰的是____________。
指向常量的指针、指针所指的字符串
[解析]根据由‘*’在修饰符“const”中位置的不同,它所修饰的对象也不同,“const”表示所修饰的是指针所指的常量,该指针称为指向常量的指针;
“*const”表示所修饰的是指针本身,该指针称为常指针;
“*const*”则表示所修饰的是指针本身和指针所指常量,该指针称为指向常量的常指针。
3.引入虚基类的目的是为了解决多重继承中的____________和____________问题。
二义性、多占用空间
[解析]在允许多重继承时可能出现两个问题,第一个是公有派生类中的成员通过不同基类调用它们上一级公共基类的同一成员,这就产生了调用的二义性;
每一个基类都为它们的上一级公共基类存有备份,这就引起了公共基类的重复存储,也就多占了存储空间。
引入虚基类的目的是为了解决多重继承中的这两个问题。
4.构造函数与析构函数所调用的虚函数是____________的函数,因此调用时实现的是____________联编。
所在类、静态
[解析]在生成派生类的对象时,先调用基类的构造函数生成基类对象,再调用派生类的构造函数来生成派生类对象。
所以当在构造函数中调用虚函数时,当调用基类的构造函数时,此时派生类还未生成,所以它只能调用自己的虚函数;
调用派生类构造函数时,它也只能调用自己的虚函数,因为虚函数的调用是不能由派生类调用基类的。
在析构派生类对象是时,先调用派生类的析构函数析构掉派生类对象,再调用基类的析构函数来析够掉基类的对象。
所以当在析够构函数中调用虚函数时,派生类的析构函数调用的是它自己的虚函数(原因同构造函数),基类的析构函数调用的也是它自己的虚函数,因为此时派生类对象以已被析构掉了。
由上可见,当构造函数与析够函数调用虚函数时,它们调用的都是自己类的函数,因此调用时实现的是静态联编。
7.说明一个const成员函数(又称常量成员函数)的方法是,将const写在__________之间,而且它修饰的是__________。
函数头与函数体、this指针
[解析]为了说明一个常量成员函数的方法是,将const写在函数头的右圆括号‘)’与函数体的左花括号‘{’之间,而且它修饰的是对象所属的this指针。
表示该函数不能修改它所在对象中的数据成员的值。
20.对某个运算符的重载,实际上是用关键字____________与该运算符组成一个运算符函数,而且该运算符函数的返回类型不能是____________的。
operater、void
[解析]对某个运算符的重载,实际上是用关键字operater与该运算符组成一个运算符函数,而且该运算符函数的返回类型不能是无类型的,即不能是void的。
三改错题
1.分析下列程序中的错误,并说明出错原因。
#include
classbase{
constintn;
public:
base(){cout<
”Initializingdefault\n”;
base(intm){cout<
”Initializing\n”;
n=m;
~base(){cout<
”Destroying\n”;
};
voidmain()
{basex
(1);
basey=x;
}
(1)n=m;
const数据成员不以该形式赋值
(2)错误处basey=x;
,以对象初始化对象
[解析]
(1)作为const数据成员n不能用赋值表达式的形式为其赋初值,必须在定义构造函数时在函数头中以“base(intm):
n(m)”形式来初始化。
(2)basey=x;
语句中‘=’不是赋值的意思,而是初始化的意思。
即在定义类base的对象y时,以对象x给它初始化,相当于basey(x);
。
但是以对象初始化对象时,必须调用拷贝构造函数才行。
因程序中没给出拷贝构造函数,也不能调用系统的缺省拷贝构造函数,因用户给出了构造函数后,再也不能调用系统提供的任何缺省构造函数。
所以,basey=x;
是错误的。
2.分析下列程序中的错误,并说明出错原因。
#include
intx;
A(inta){x=a;
fun();
virtualvoidfun()=0;
publicA{
B(intb):
A(b){}
voidfun(){}
{Aaa(5);
Bbb(8);
答:
1)Aaa(5);
抽象类不能定义对象
[解析]
(1)在构造函数“A(inta)”调用了纯虚函数“fun()”,因构造函数调用虚函数是静态联编,即调用的是它自己类的虚函数。
在此调用的是纯虚函数,它只被说明,而未定义,所以不可能被执行,因此出错。
(2)抽象类相当于是对类的引用性声明,所以它只能定义该类的指针和引用,而不能定义它的对象。
在此,A为抽象类,而“Aaa(5)”却定义了A的对象,因此是错误的。
3.分析下列程序中的错误,并说明出错原因。
#include
classAA{
intaa;
AA(intxx){aa=xx;
intget(){returnaa;
~AA(){cout<
”Destroying”<
AA<
endl;
main()
{AAelem(5);
cout<
elem.get()<
endl;
(1)AA(intxx)的访问属性错、应具有公有属性
[解析]
(1)构造函数虽是由系统自动调用来生成对象的,但一般都是在类外调用,所以它的访问属性必须是公有的。
程序中构造函数的访问属性是私有的(缺省值),运行中必定出错。
四.完成程序题(本大题共5小题,每小题4分,共20分)
根据题目要求,完成程序填空。
1.仔细阅读下列求两个点之间距离的程序,根据程序的输出结果在划线处填入正确语句。
classpoint{
floatx,y;
point(floata,floatb){x=a;
y=b;
floatdistance(point&
p){
floatdx=_____①______;
floatdy=_____②______;
return(float)sqrt(dx*dx+dy*dy);
voidmain()
{pointp1(2,3),p2(32,43);
p1.___③___<
答:
①p.x-x
②p.y-y
③distance(p2)
[解析]由于求两点之间距离的函数“distance”为成员函数,所以由该函数的this指针所指对象可用作起点(参数之一),另一个用作终点的参数,必须在函数的参数表中显式地给出。
dx和dy分别计算两个结点间x和y坐标间的距离,因此应该为:
dx=p.x–x和dy=p.y–y。
对它们求平方相加后开方即可,得到两点间的距离:
(float)srrt(da*da+dy*dy)。
在主程序中求p1和p2两个结点之间的距离,由于由p1调用距离函数,所以由p2作为它的参数,即distance(p2)。
2.两个复数只有当它们的实部和虚部分别相等时,才被认为它们相等。
在空格处填入合适的内容,以完成下面的程序,使其重载运算符“==”,用以比较两个复数的相等。
请在主函数中输出比较的结果。
classcomplex{
doublereal,imag;
complex(doubler,doublei){real=r;
imag=i;
booloperator==(complex&
);
intcomplex:
operator==(complex&
com)
{return(_____①_____)}
{complexc1(12.3,32.5),c2(21.7,18.6);
if(______②______)
returncout<
”true\n”;
else
”false\n”;
答:
①(real==com.real)&
&
(imag==com.imag)
②c1==c2或c1.operator==(c2)
[解析]若两个复数的相等,则必有它们的实数部分和虚数部分都相等,所以运算符重载函数中返回“(real==com.real)&
(imag==com.imag)”,只有real==com.real与imag==com.imag都为真时,该函数的返回值才为真。
在主程序中,为了比较两个复数c1和c2,可以隐式地写成“c1==c2”,也可显式写成“c1.operator==(c2)”。
3.下列程序中声明了两个类AA和BB,其中函数“print”是类AA的成员函数,但是类BB的友元函数。
请在①、②和③处各填入正确的内容,使程序能正常运行。
_____①______;
intt;
AA(intx){t=x;
voidprint(BB&
b);
classBB{
ints;
BB(inty){s=y;
friendvoid___②___print(BB&
void____③_____
{cout<
”AA:
”<
T<
”;
BB:
W.S<
}
{AAm(6);
BBn(8);
m.print(n);
答:
①classBB;
②AA:
③AA:
print(BB&
w)
[解析]由于AA类的成员函数“print”是类BB的友元函数,因此它必须有一个BB类的引用作为参数,以便有引用BB类数据成员的接口。
但此时BB类还未定义,为解决此矛盾,在①处先对BB类作引用性声明“classBB;
”,告诉系统BB类在后面定义。
因为函数“print”是类AA的成员函数,在类外定义必须加上类名和作用域分辨符,即在②处加上“AA:
在BB类外定义“print”时,因是友元,所以没有加上“BB:
”的必要,但“AA:
”还是必须加的,所以在③处填“AA:
w)”。
五.程序分析题
1.请分析以下的程序,给出该程序的正确执行结果。
#include<
iostream>
usingnamespacestd;
intadd(intx,inty)
{
returnx+y;
voidmain()
intm=2,n=3;
cout<
"
1:
add(m++,m+n)<
m=2,n=3;
2:
add(++m,m+n)<
3:
add(m+n,m++)<
4:
add(m+n,++m)<
}
7
2:
8
3:
4:
9
[解析]在说明答案之前,要说明两个问题:
1)C++语言中,函数参数是压在栈里的,因压栈是从前往后进行的,所以出栈就是从后向前进行的,也即先取最后的参数,然后再向前逐个取用;
2)对于单加运算,m++是先执行后加1,++m是加1后再执行。
由此,因m=2,n=3;
,所以:
(m++)+(m+n)=2+(2+3)=7(m++后执行,且后加1,所以m=2一直未变)
(++m)+(m+n)=3+(2+3)=8(++m后执行,但先加1,执行++m时,m=3了)
(m+n)+(m++)=(3+3)+2=8(先执行m++,后加1,执行m+n时,m=3了)
(m+n)+(++m)=(3+3)+3=9;
(先执行++m,且先加1,故一开始就有m=3)
3.请分析下面的程序并给出该程序的执行结果。
inta;
AA(){cout<
”InitualizingAA!
\n”;
”DestroyingAA!
intb;
AAp;
BB(){cout<
”InitualizingBB!
~BB(){cout<
”DestroyingBB!
{BBX;
”Endingmain!
InitualizingAA!
In
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 面向 对象 程序设计 习题