一首很好听但不那么主流的歌曲,挺好听的

2022年C++试卷软件学院

1.I in C++ , There is a kind of class that it can only be inherited but cannot be initiated, we call that class as a ( ),to define that kind of class, it has to have at least a ( ) 。

  1. virtual function
    (B) pure virtual function (C) abstract class
    (D)friend class

在C++中,有一种类只能被继承但不能被实例化,我们称之为(抽象类)。要定义这种类,它至少必须有一个(纯虚函数)。

在C++中,有一种类只能被继承而不能被实例化,我们称之为(C)抽象类。要定义这种类,它至少必须拥有一个(B)纯虚函数。抽象类中的纯虚函数是没有实现的虚函数,它的声明以 "= 0" 结尾,派生类必须实现这些函数才能被实例化。因此,抽象类的存在主要是为了作为其他类的基类,提供一个通用的接口,但它本身无法被实例化。

抽象类是一个不能被实例化的类,它存在的目的是为了被其他类继承,派生出新的类。抽象类至少要包含一个纯虚函数,这样的函数没有具体的实现,必须由派生类提供实现。由于抽象类中至少有一个纯虚函数,因此它不能被实例化,只能被其他类继承。

2. Assume that AB is a class, the declaration of copy constructor of that class should be ( )。

(A)AB&(AB x)
(B)AB(AB x)
(C)AB(AB &x)
(D)AB(AB *x)

很基本的拷贝构造函数知识点

假设AB是一个类,那么该类的拷贝构造函数的声明应该是:

(C)AB(AB &x)

拷贝构造函数用于创建一个对象,并将其初始化为另一个同类型对象的副本。在C++中,拷贝构造函数通常采用引用作为参数,因为使用引用可以避免不必要的对象复制。参数应该是一个对同类型对象的引用,这样可以通过引用访问源对象的成员,并将其复制到正在构造的新对象中。

3. For the member of a structure, the default access modifier is ( )。

(A) public; (B) private; (C) protected; (D) static;

对于结构体的成员,其默认访问修饰符是: Public, 在C++中,对于类(class)来说,类的默认访问修饰符是private,而不是public。然而,对于结构体(struct)来说,默认访问修饰符是public

因此,在结构体(struct)中,成员的默认访问修饰符是public,而不是private

在C++中,如果在结构体定义中没有显式指定访问修饰符,则默认情况下,结构体的成员都是私有的(private)。这意味着结构体的成员只能在结构体内部被访问,外部无法直接访问。

这也是类和结构体的区别啊

4.Assume AB is a class, to execute statement “AB a(4),b[3],*p[2];”, how many times to invoke the constructor?( )。

  1. 3
    (B) 4
  2. 6
  3. 9

假设AB是一个类,在执行语句“AB a(4), b[3], *p[2];”时,构造函数会被调用多少次?

答案是:

  1. 4

这个语句中,执行了以下操作:

  1. 创建了一个名为a的对象,并调用了构造函数AB(int)一次。
  2. 创建了一个名为b的数组,包含3个元素,因此会调用构造函数AB()三次,总共调用3次构造函数。
  3. 创建了一个名为p的指针数组,包含2个元素,没有初始化,因此不会调用构造函数。

所以,总共调用了4次构造函数。

5. Which of the following is not correct ( )

  1. The name of constructor is same as the name of the class

  2. class constructor could have default parameters

(C) the default return type of a constructor is of type int

  1. the constructor can be overloaded

正确答案是:

  1. the default return type of a constructor is of type int

解释:

  1. 构造函数的名称与类的名称相同,这是正确的。构造函数没有显式的返回类型,它们不会返回任何值,因此其名称仅用于标识和与类关联。
  1. 类的构造函数可以具有默认参数。默认参数可以使构造函数在调用时更加灵活,允许在不提供参数值的情况下使用构造函数。
  1. 构造函数可以进行重载,即在同一个类中可以有多个构造函数,它们具有相同的名称但不同的参数列表。这允许在创建对象时提供不同的初始化方式。
  1. 构造函数没有返回类型,因此不存在默认返回类型。构造函数的主要目的是初始化对象的成员变量,而不是返回任何值。这个错的太明显了,构造函数显然没有返回类型

6.Parameterized stream manipulator setfill specifies the fill character that is displayed when an output is displayed in a field wider than the number of characters or digits in the output. The effect of setfill applies:

参数化流操作符 setfill 用于指定在输出显示的字段宽度大于输出中字符或数字的数量时所显示的填充字符。setfill 的效果适用于哪些情况?

  1. Only to the current value being displayed. 仅适用于当前显示的值:这意味着 setfill 设置的填充字符仅适用于当前正在显示的值,一旦值显示完毕,填充字符设置将被重置为默认值。

  2. Only to outputs displayed in the current statement. (B) 仅适用于当前语句中的输出:这意味着 setfill 设置的填充字符仅适用于当前语句中的输出,一旦语句结束,填充字符设置将被重置为默认值。

(C) Until explicitly set to a different setting.

  1. Until the output buffer is flushed.

直到输出缓冲区被刷新:这意味着 setfill 设置的填充字符将一直有效,直到输出缓冲区被刷新为止。输出缓冲区在满足一定条件时会被刷新,例如缓冲区已满、程序结束时,或者调用了 flush 或 endl 等刷新输出流的函数。

选项 (C) 表示 setfill 的效果会一直持续,直到显式地使用其他设置将其更改为不同的值。这意味着一旦使用 setfill 设置了填充字符,该设置将在后续的输出中继续有效,直到程序明确地使用另一个填充字符进行更改。

看过书可能知道这是因为他是粘性的,下面讲解一下知识点 在C++中,setfill 是一个标准库中的操纵算子(manipulator),用于设置流(stream)中填充字符(fill character)。当你在格式化输出时,setfill 可以用来指定在宽度不足的情况下填充的字符。

以下是一些关于 setfill 的知识点:

语法

1
2
3
4
#include <iostream>
#include <iomanip>

std::cout << std::setfill('c');

示例代码

下面是一些使用 setfill 的示例:

  1. 基本使用:
1
2
3
4
5
6
7
#include <iostream>
#include <iomanip>

int main() {
std::cout << std::setfill('*') << std::setw(10) << 123 << std::endl;
return 0;
}

输出:

1
*******123

在这个示例中,std::setw(10) 指定了宽度为10,std::setfill('*') 指定了填充字符为 *。因此,数字 123 前面会填充7个 * 以达到指定的宽度。

  1. 与其他操纵算子结合使用:
1
2
3
4
5
6
7
8
9
#include <iostream>
#include <iomanip>

int main() {
int num = 42;
std::cout << std::setfill('0') << std::setw(5) << num << std::endl;
std::cout << std::left << std::setfill('-') << std::setw(10) << num << std::endl;
return 0;
}

输出:

1
2
00042
42--------

在这个示例中: - 第一行使用 std::setfill('0')std::setw(5),将数字 42 前面填充3个 0。 - 第二行使用 std::leftstd::setfill('-')std::setw(10),将数字 42 左对齐,并在右侧填充 - 以达到指定的宽度。

注意事项

  • setfill 只影响后续输出的填充字符,直到遇到下一个 setfill 设置。
  • setw 只影响后续的单个输出操作,不是永久性的设置。

总结

setfill 是一个非常有用的操纵算子,当你需要在格式化输出中指定填充字符时,可以使用它来简化代码并提高可读性。 ***

7. Assuming the following is the beginning of the constructor definition for class Circle which inherits from class Point,

(假设以下是类 Circle 的构造函数定义的开始部分,该类继承自类 Point。) Circle::Circle( double r, int a, int b )

: Point( a, b ) The second line:

(A) Invokes the Point constructor with values a and b

调用带有值 a b Point 构造函数:这个选项是正确的。构造函数初始化列表中的 Point(a, b) 部分表示在构造 Circle 对象时,首先调用 Point 类的构造函数,并传递参数 a b。这确保了在构造 Circle 对象时,先初始化 Point 类的成员。

  1. Causes a compiler error.实际上并不会导致编译错误

  2. Is unnecessary because the Point constructor is called automatically. 是不必要的,因为 Point 构造函数会自动调用:这个选项也是错误的。虽然在创建 Circle 对象时,会自动调用 Point 类的构造函数来初始化继承的成员,但是在构造函数定义中显式调用基类的构造函数是一种良好的编程实践,它确保了正确的初始化顺序和参数传递。

  3. Indicates inheritance.

D也可以说对,但是不能说这里体现,这里主要还是初始化父类

  1. 表示继承比较多。

解释:

这行代码指示了 Circle 类从 Point 类继承。使用 : Point(a, b) 的语法表示在构造 Circle 类对象时,首先调用 Point 类的构造函数,并传递参数 a 和 b。这样做是为了在构造 Circle 对象时,先初始化 Point 类的成员,以确保 Circle 对象正确地继承了 Point 类的属性和行为。


8. Which of the following assignments would be a compilation error?

  1. Assigning the address of a base-class object to a base-class pointer.

(B) Assigning the address of a base-class object to a derived-class pointer.

  1. Assigning the address of a derived-class object to a base-class pointer.

  2. Assigning the address of a derived-class object to a derived-class pointer.

以下哪个赋值操作会导致编译错误?

  1. 将基类对象的地址赋给基类指针。

  2. 将基类对象的地址赋给派生类指针。

  3. 将派生类对象的地址赋给基类指针。

  4. 将派生类对象的地址赋给派生类指针。

答案是:

  1. 将基类对象的地址赋给派生类指针。

解释:

赋值操作 (B) 尝试将一个基类对象的地址赋给一个派生类指针,这会导致编译错误。派生类指针只能指向派生类对象,不能指向基类对象。这是因为基类对象和派生类对象的内存布局通常不同,派生类对象可能包含基类对象的成员以及自己独有的成员,因此将基类对象的地址赋给派生类指针可能会导致指针指向错误的内存位置,违反类型安全性。 ***

9. Assume class T is declared as following,which of the following declaration of the function fF() is not correct( )。

1
2
3
4
5
6
7
class T

{ int i;

friend void fF(T&,int) ;

};
  1. void fF (T &objT,int k) { objT.i = k+1; }

  2. void fF (T &objT,int k) { k = objT.i+1; }

(C) void T::fF (T &objT,int k) { k += objT.i; }

  1. void fF (T &objT,int k) { objT.i += k; }

选项 (C) 是不正确的。在类外部声明的友元函数不能使用类的作用域解析运算符 (::),因为它们不是类的成员函数。因此,在选项 (C) 中,使用了类作用域解析运算符是错误的。友元函数应该在类的外部定义,不应该使用类作用域解析运算符。

友元不属于类的一部分