习题集1
判断题
1-1
对单目运算符重载为友元函数时,可以说明一个形参。而重载为成员函数时,不能显式说明形参。(T)
【解答】:回忆知识点,双目重载为友元2个形参,重载为成员1个形参(还有一个参数默认是this指针);单目重载为友元1个形参,重载为成员0个形参(一个参数默认是this指针)
1-2
虚函数是用virtual 关键字说明的成员函数。(T)
1-3
使用提取符(<<)可以输出各种基本数据类型的变量的值,也可以输出指针值。(T)
1-4
因为静态成员函数不能是虚函数,所以它们不能实现多态。(F)
1-5
重载operator+时,返回值的类型应当与形参类型一致。
比如以下程序中,operator+的返回值类型有错:
1 | class A { |
(F)
【解答】operator+
的返回类型并不需要与参数类型一致。实际上operator+
通常返回结果的类型可能与参数类型完全不同。
单选题
2-1
对象之间的相互作用和通信是通过消息。( )不是消息的组成部分。
A.接受消息的对象
B.要执行的函数的名字
C.要执行的函数的内部结构
D.函数需要的参数
2-2
( )不是面向对象程序设计的主要特征。
A.封装
B.继承
C.多态
D.结构
2-3
对定义重载函数的下列要求中,( )是错误的。
A.要求参数的个数不同
B.要求参数中至少有一个类型不同
C.要求函数的返回值不同
D.要求参数个数相同时,参数类型不同
2-4
关于动态绑定的下列描述中,( )是错误的。
A.动态绑定是以虚函数为基础的
B.动态绑定在运行时确定所调用的函数代码
C.动态绑定调用函数操作是通过指向对象的指针或对象引用来实现的
D.动态绑定是在编译时确定操作函数的
【解答】运行时确定的
2-5
关于虚函数的描述中,( )是正确的。
A.虚函数是一个static 类型的成员函数
B.虚函数是一个非成员函数
C.基类中说明了虚函数后,派生类中与其对应的函数可不必说明为虚函数
D.派生类的虚函数与基类的虚函数具有不同的参数个数和类型
【解答】虚函数是成员函数;基类的虚函数无论被公有继承多少次,在多级派生类中仍然为虚函数;派生类的虚函数与基类的虚函数具有相同的参数个数和类型
2-6
下列叙述中,不正确的是( )。
A.构造函数必须和类同名
B.构造函数和析构函数都没有返回值
C.析构函数中不能加代码
D.析构函数不能带参数
2-7
在下面类声明中,关于生成对象不正确的是( )。
1 | class point |
A.point p(10,2);
B.point *p=new point(1,2);
C.point *p=new point[2];
D.point *p[2]={new point(1,2), new point(3,4)};
2-8
下列运算符中,( )运算符不能重载。
A.&
B.[ ]
C.::
D.<<
2-9
关于纯虚函数和抽象类的描述中,( )是错误的。
A.纯虚函数是一种特殊的虚函数,它没有具体的实现
B.抽象类是指具有纯虚函数的类
C.一个基类中说明有纯虚函数,该基类的派生类一定不再是抽象类
D.抽象类只能作为基类来使用,其纯虚函数的实现由派生类给出
【解答】纯虚函数是在声明虚函数时被“初始化”为0的虚函数。不定义对象而只作为一种基本类型作为继承的类,称为抽象类。凡是包含纯虚函数的类都是抽象类。抽象类的作用是作为一个类族的共同基类。
2-10
在下列关键字中,用以说明类中公有成员的是( )。
A.
public
B.private
C.protected
D.friend
程序填空题
5-2
CAT’s Copy
阅读下面的程序,完成其中复制构造函数的代码。
1 |
|
- 【解答】
itsAge = new int; // 分配新的内存空间
*itsAge = *(c.itsAge); // 复制传入对象的itsAge的值
习题集2
填空题
1
write the output of the code below.
1 |
|
- 【解答】
- 1.
1
- 2.
3
- 3.
5
- 1.
2
write the output of the code below.
1 |
|
- 【解答】
- 1.
0
- 2.
0
- 3.
1
- 4.
1
- 1.
习题集3
填空题
1
write the output of the code below.
1 |
|
- 【解答】
10#21
在
main
函数中,定义了一个整数k
并初始化为0然后,它调用函数
f
,将k
作为引用参数传入。在函数f
中,参数i
是对k
的引用,所以i += 10;
实际上是将k
的值增加10。所以,k
的值现在是10。函数f
返回对k
的引用,这个引用被赋给了m
cout << k << "#";
将输出10#
接下来,
f(m)++
再次调用了函数f
,这次传入的是m
,m
实际上是对k
的引用,所以i += 10;
再次将k
的值增加10,k
的值现在是20。函数f
返回对k
的引用,然后++
操作将k
的值增加1,所以k
的值现在是21- 高亮解释
- 高亮解释
最后,
cout << k << endl;
将输出21
2
write the output of the code below.
1 |
|
- 【答案】
- 1.
***
- 2.
***
- 3.
***
- 4.
0
- 5.
1
- 1.
- 【解答】
- 最初a=0,++a进入
counter &counter::operator++()
前置递增 - 第一次
++a
,a=1,输出*** - 第二次
++a
,a=2,输出*** - 第三次
++a
后,a=3,输出*** - 第四次
++a
,a=0,不进去 - a=0,输出0
- a++进入
int counter::operator++(int)
后置递增 - 第一次
a++
,while(a)中a=0不进去,然后a自增=1 - a=1,输出1
- 最初a=0,++a进入
3
1 |
|
- 输出
154
- 自己算一下
习题集4
填空题
1
write the output of the code below.
1.the output at //1 is
2.the output at //2 is
3.the output at //3 is
4.the output at //4 is
5.the output at //5 is
1 |
|
- 【答案】
- 1.
1
- 2.
2
- 3.
7
- 4.
0
- 5.
0
- 1.
- 【解析】
- 注意第三题是7,length不包括
\0
- 注意第三题是7,length不包括
2
write the output of the code below.
1 |
|
- 【答案】
- 1.
dog!
- 2.
dog!
- 3.
pet!
- 注意是纯虚函数不能实例化,虚函数是可以的!
- 1.
3
重复 过
4
write the output below
1 |
|
- 【答案】
- 1.
1
- 2.
2
- 3.
3
- 4.
11
- 5.
12
- 1.
5
重复,过
6
1 |
|
- 【解答】
- 1.
1
- 2.
0,2
- 3.
0
- 1.
- 【解析】
b.display()
调用的是Base
类的display()
函数,因为b
是Base
类型的对象。Base
类的display()
函数会输出x
的值,所以这行代码会输出1
。d.display()
调用的是Derived
类的display()
函数,因为d
是Derived
类型的对象。Derived
类的display()
函数会输出x
和y
的值。这里需要注意的是,尽管Derived
类没有显式地初始化x
,但是x
会被Base
类的构造函数初始化为0
,而y
会被Derived
类的构造函数初始化为2
。所以这行代码会输出0,2
。Derived
类的display()
函数并没有被声明为override
,并且它的函数签名与Base
类的display()
函数不同,因为它不是const
函数。所以,实际上Derived
类并没有重写Base
类的display()
函数,而是定义了一个新的display()
函数。当p->display()
被调用时,由于p
是一个Base
类型的指针,所以会调用Base
类的display()
函数,而不是Derived
类的display()
函数。Base
类的display()
函数会输出x
的值,由于p
指向的是Derived
对象d
,而d
的x
值在Derived
的构造函数中并未被显式初始化,所以它的值是由Base
的构造函数初始化的,为0
。- 对第三行的错误解释(错的!):
p->display()
调用的是Derived
类的display()
函数,因为p
是一个指向Derived
对象的Base
类型的指针。C++中,当通过基类的指针或引用调用一个虚函数时,会根据指针或引用实际所指向的对象类型来决定调用哪个函数。
- 对第三行的错误解释(错的!):
- 【改编】
- 如果
virtual void display() { cout << x << endl; }
改成virtual void display() const { cout << x << endl; }
- 输出就是
1
,0,2
,0,2
- 输出就是
- 如果
void display() { cout << x << "," << y << endl; }
改成void display() overide { cout << x << "," << y << endl; }
- 输出就是
1
,0,2
,0,2
- 输出就是
- 如果同时改上面2个会报错
- 如果
习题集5
填空题
5
write the output of the code below.
1 |
|
- 【答案】
- 1.
2
- 2.
1
- 1.
- 【解答】
- 这段代码中,
C
类包含了A
类和B
类的对象,以及一个int
类型的变量。在main
函数中,使用了C
类对象之间的赋值操作m = n;
。由于C
类没有定义自己的赋值运算符operator=
,所以编译器会为C
类生成一个默认的赋值运算符。 - 默认的赋值运算符会按照成员在类中声明的顺序,依次调用每个成员的赋值运算符。在
C
类中,成员的声明顺序是B b, A a, int c
,所以在执行m = n;
时,首先调用B
类的赋值运算符,然后调用A
类的赋值运算符,最后赋值int
类型的成员。 B
类的赋值运算符输出数字2
,A
类的赋值运算符输出数字1
,所以程序的输出结果是2 1
。而int
类型的赋值操作不会产生输出,所以没有其他输出。
- 这段代码中,
6
write the output of the code below.
1 |
|
- 【答案】
- 1.
2
- 2.
1
- 1.