C++ 练习试卷(一)解析

练习试题卷(一)

这是 C++ 练习试题卷。
答案与解析仅供参考,若有误欢迎指出。

单选题

1. 下列选项中不是 C++ 语言关键字的是:

  • A、typedef
  • B、mycase
  • C、typeid
  • D、int

【答案】B、mycase

【解析】 本题中,typedef 关键字用于创建类名,typeid 关键字用于在运行时获知变量名称,int 关键字用于声明证书类型。而 mycase 并不是 C++ 语言中的关键字。

关键字: 在 C++ 当中,关键字是系统预先定义好的标识符,编译器会对其做特殊处理。关键字又称为保留字,这些保留字不能够作为常量名、变量名或其他标识符名称。

2. 下列选项中不是 C++ 语言合法标识符的是:

  • A、area
  • B、_age
  • C、-xy
  • D、w123

【答案】C、-xy

【解析】 本题中,area_agew123 即不属于系统定义的关键字,也符合标识符的命名规则。而 -xy 是以短横线 - 开头,不符合标识符书写规范中的 「以大小写字母或下划线 “_” 开头」的规定。

标识符: 在 C++ 当中,标识符是用来标识变量、函数、类、模块,或者任何其他用户自定义项目的名称。它是用来命名程序正文中的一些实体,比如函数、变量名、类名、对象名等。

标识符可以由大写字母、小写字母、下划线 “ _ ”和数字 0~9 组成,但必须是以大写字母、小写字母、下划线 “ _ ” 开头。在 C++ 语言程序中,大小写字母不能混用,编译器对大小写敏感。

3. 下列选项中正确的标识符是:

  • A、case
  • B、de。fault
  • C、c_ase
  • D、a.b

【答案】C、c_ase

【解析】 标识符作为用户定义的名称,不能够与系统事先定义的关键字重复,并且需要遵循标识符的命名规则。本题中,case 是系统定义的关键字,de。fault 中包含了不合规则的全角句号 a.b 也包含了不合规则的小数点 . 。故 c_ase 是正确的标识符。

4. C++ 语言程序中,出现条件分支语句 ifelse 的时候,else 与 ________ 组成配对关系。

  • A、同一复合语句内部的 if
  • B、在其之前任意的 if
  • C、在其之前未配对的最近的 if
  • D、首行位置相同的 if

【答案】C、在其之前未配对的最近的 if

【解析】 在 C++ 中,else 语句与最近的、未配对的 if 配对。这意味着如果程序中存在多个 if 语句的嵌套,else 会优先配对离它最近的、未配对的 if。例如:

if (condition1)
{
    if (condition2)
    { ... }
    else  // 此处将与 if(condition2) 配对
    { ... }
}
else // 由于 if(condition2) 已经被配对了,所以此处将与 if(condition1) 配对
{ ... }

5. 下列数组定义方式不正确的语句是:

  • A、char x[5];
  • B、char y[] = {'h','e','l','l','o'};
  • C、int x[10] = {12, 13, 14, 15};
  • D、int y[];

【答案】D、int y[];

【解析】

  • A、这是正确的数组定义方式。该语句声明了一个包含有 5 个元素的字符数组。
  • B、这也是正确的定义方式,根据初始化列表确定了数组的大小,定义了包含 5 个字符的数组。
  • C、这是正确的定义方式。数组长度是 10,语句初始化了 4 个元素,所以剩下 6 个元素将会自动被赋值为 0。
  • D、这是错误的定义方式。在声明数组的时候必须指定数组的大小或者提供足够的初始化元素来确定数组的大小。这里缺少了数组的大小,也没有提供初始化的值,会导致发生错误。

数组是一个集合,用于存放相同类型的数据元素,并且数组将会占用一段连续的内存空间。

在定义数组的时候,必须指定初始长度或者给出数组的初始值,或是定义长度之后再定义初始值。若初始化的时候初始值元素个数小于数组定义长度,则剩余元素会使用 0 填充。

6. 若有如下定义语句,且 0 ≤ i < 5 0 \leq i < 5 0i<5 ,下面 _____ 是对数值为 3 数组元素的引用。

int a[] = {1, 2, 3, 4, 5}, *p, i;
p = a;
  • A、*(a+2)
  • B、a[p-3]
  • C、p+2
  • D、a+3

【答案】A、*(a+2)

【解析】

  • *(a+2): 这是对数组元素的引用,等同于 a[2],即数组中第三个元素,其值为 3。
  • a[p-3]: 这样的引用方式是不正确的。因为 p 是一个指针,而不是数组的索引。应该使用 *(a+p-3)
  • p+2: 这是对指针 p 的引用,指向数组的起始地址,加上 2 相当于指向数组的第三个元素。但这并不是对数组元素 3 的引用。
  • a+3: 这是数组地址的引用,指向数组的第四个元素的地址。不是对元素 3 的引用。

因此,正确答案是 A、*(a+2),它引用了数组中的第三个元素,其值为 3。

7. 对于两个函数,若函数名相同,但只是 ____ 不同,则不是重载函数。

  • A、参数类型
  • B、参数个数
  • C、函数类型
  • D、参数顺序

【答案】C、函数类型

【解析】 函数重载需要避免二义性,保证返回值、函数名和作用域必须相同。本题中,若函数类型,也就是函数的返回值不相同,它就不是重载函数。故选 C。

在传统的 C语言当中,函数名必须是唯一的,程序中不允许出现同名的函数。在 C++ 中,可以通过函数重载(Overload)让函数名称重复定义。函数重载的目的是为了方便使用函数名。

函数重载切记要避免二义性,只能够以参数作为唯一的区别,其返回值函数名作用域必须完全相同,函数的参数类型、个数和顺序可以不同。

8. C++ 语言中定义类的关键字是:

  • A、while
  • B、union
  • C、class
  • D、for

【答案】C、class

【解析】 本题考察对关键字的认识与使用。

  • while 关键字用于定义一个循环,当给定的条件为真时,该语句会重复执行给定的目标语句。
  • union 关键字用于定义一个联合,它是一个特殊的类,一个联合中只能有一个数据成员能够拥有值。当联合中某个成员被赋值之后,其他成员就会变成未定义的状态。
  • class 关键字用于定义一个类。类用来描述对象,它是由用户自定义的数据类型,并且该类型的数据能够有一定的行为能力。
  • for 关键字用于定义一个循环。给定初始化、执行条件和自增条件,即可执行特定次数的重复循环结构。

根据题目,用于定义一个 C++ 类的关键字应当是 C、class

9. 由 C++ 目标文件连接而成的可执行文件的缺省拓展名为 _____

  • A、.cpp
  • B、.exe
  • C、.obj
  • D、.lik

【答案】B、.exe

【解析】

  • .cpp 是 C++ 源代码文件的拓展名。
  • .exe 是 Windows 上的可执行文件拓展名,由 C++ 目标文件连接而成的可执行文件通常使用此拓展名。
  • .obj 是目标文件(Object File)的拓展名,它是编译源代码时生成的中间文件,需要连接器将多个目标文件连接成可执行文件。
  • .lik 不是用于表示 C++ 可执行文件的拓展名。

综上,答案为 B、.exe

10. 在下面有关友元函数的描述中,正确的说法是:

  • A、友元函数是独立于当前类的外部函数。
  • B、一个友元函数不能同时定义为两个类的友元函数。
  • C、友元函数必须在类的外部定义。
  • D、在外部定义友元函数时,必须添加关键字 friend

【答案】A、友元函数是独立于当前类的外部函数。

【解析】 首先简单回顾一下什么是「友元」。

生活中你的家有客厅(public),有你的卧室(private)。客厅所有来的客人都可以进去,但是你的卧室是私有的,也就是说只有你可以进去。

但如果你想的话,你可以允许隔壁老王进入你的卧室。

在程序里,有些私有属性也想让类外的一些特殊的函数或者类访问,就可以使用到友元技术。

—— from 《C++:友元(看这一篇就够了)》 by 孙 悟 空

友元函数 是定义在类的外部,但有访问类的所有私有(private)成员和保护(protected)成员的权限。

友元可以是一个函数,也可以是一个类。在友元类中,整个类及其成员都是友元。

据此,分析题目:

  • A、正确。友元是定义在当前类外部的,因为你这个朋友不能是你自己。
  • B、错误。一个友元函数可以同时定义为多个类的友元函数。
  • C、错误。友元函数可以在类的内部声明,在类的外部定义。
  • D、错误。虽然在类的声明中需要使用 friend 关键字声明友元函数,但是在外部定义的时候不需要添加 friend 关键字。

因此,答案选 A、友元函数是独立于当前类的外部函数。

填空题

1. C++ 语言中用来处理标准输入的是 _____。

【答案】cin

【解析】 cin 是 C++ 中的输入流对象,也属于标准命名空间 std 中的一部分。通过 cin 可以从标准输入设备(通常是键盘)接收输入数据。

#include <iostream>

int main() {
    int number;
    
    std::cout << "Enter a number: ";
    std::cin >> number;

    std::cout << "You entered: " << number << std::endl;

    return 0;
}

在上面的例子中,std::cin 用来接收用户输入的整数,并将其存储到变量 number 中。

2. C++ 语言中用来处理标准输出的是 _____。

【答案】cout

【解析】 cout 是 C++ 中的输出流对象,属于标准命名空间 std 中的一部分。通过 cout 可以向标准输出设备(通常是控制台)输出数据。

#include <iostream>

int main() {
    std::cout << "Hello world!" << std::endl;
    return 0;
}

上面的例子中,std::cout 被用来输出字符串 “Hello world!” 到标准输出设备,并在末尾添加了换行符 std::endl

3. 定义内联函数的关键字是 _____

【答案】inline

【解析】 定义内联函数的关键字是 inline。使用 inline 关键字可以建议编译器将函数的代码嵌入到调用处,而不是通过常规的函数调用机制进行调用。这样可以减少函数调用的开销,提高程序的执行效率。

inline int add(int a, int b) {
    return a + b;
}

int main() {
    int result = add(3, 4);  // 编译器可能会将此处的函数调用直接替换为 add 函数的代码
    return 0;
}

需要注意的是,inline 关键字只是一种对编译器的建议,编译器可以选择忽略这个建议。通常,较小的、频繁调用的函数更容易被编译器选择进行内联。

4. 构造函数是和 _____ 同名的函数

【答案】类

【解析】 构造函数(constructor)是和 同名的函数。在C++中,构造函数是一种特殊的成员函数,它在对象创建时自动调用,用于初始化对象的成员变量。构造函数的名称必须与类名相同,它没有返回类型,甚至不写 void。每个类可以有一个或多个构造函数,它们可以根据参数的不同进行重载。

5. 一个类有 _____ 个析构函数。

【答案】一

【解析】析构函数(destructors)的作用是在对象销毁时进行清理工作,释放对象占用的资源。类只能有一个析构函数,并且不能带有参数。如果没有显式定义析构函数,编译器会生成一个默认的析构函数。

6. 访问控制权限有public、private和 _____ 三种。

【答案】protected

【解析】 访问控制权限有 publicprivateprotected 三种。这三种访问权限决定了类的成员在类的内部和外部的可见性和可访问性,他们允许程序员灵活地控制类的接口和实现的封装性。

  • public: 公有权限表示成员对于类的外部是可访问的。在类的外部,可以通过对象访问公有成员。
  • private: 私有权限表示成员对于类的外部是不可访问的。只有在类的内部的成员函数中可以访问私有成员。
  • protected: 保护权限在继承中起到重要作用,表示成员对于类的外部是不可访问的,但对于派生类的成员函数是可访问的。

7. 在公有派生中,基类的保护成员在派生类中是 _____。

【答案】受保护的

【解析】 在公有派生(public inheritance)中,基类的保护成员在派生类中仍然是保护成员。这意味着在派生类的成员函数中可以访问基类的保护成员,但在派生类的外部不可以直接访问基类的保护成员。

8. 析构函数不允许有 _____。

【答案】返回类型

【解析】 析构函数不允许有返回类型。析构函数是一个特殊的成员函数,用于在对象被销毁时执行清理工作。与其他成员函数不同,析构函数的名称前面必须加上波浪号 ~,并且它不允许有返回类型,包括 void

9. C++函数参数传递的方式有传值和 _____ 两种。

【答案】引用

【解析】 C++函数传递参数的方式:

  • 传值(by value): 将实际参数的值传递给函数的形式参数。在函数内部对形式参数的修改不会影响实际参数。
  • 引用(by reference): 将实际参数的引用传递给函数的形式参数。在函数内部对形式参数的修改会影响实际参数。

使用引用可以避免传值时产生的额外内存开销,同时允许函数修改调用者提供的数据。

10. 释放内存可以使用关键字 _____。

【答案】delete

【解析】 在C++中,当使用 new 操作符动态分配内存时,应该使用 delete 操作符来释放已分配的内存,以防止内存泄漏。

判断题

1. 一个类可以有多个构造函数。

【答案】正确

【解析】 在 C++ 当中,一个类可以拥有多个构造函数,它们都是通过函数重载(overload)实现的。

2. 构造函数不是类的成员函数。

【答案】错误。构造函数是类的成员函数。

【解析】 构造函数是且只能是类的成员函数。构造函数是一种特殊的成员函数,它与类的名字相同,主要负责初始化新建的对象。

3. 定义析构函数时,可以指定返回类型为 void

【答案】错误。定义析构函数时,不可以指定返回类型。

【解析】析构函数主要负责对象在生命周期结束的时候(例如对象作用域结束,或通过 delete 动态删除分配的对象时)执行清理工作。它与类名相同,但需要在类名前加上波浪号 ~,并且不能拥有返回类型,包括 void 也不应该指定。同时,它通常也不接受任何参数。

4. 判断下列语句的正误:const int a;

【答案】错误。const int a = 10;

【解析】 该语句定义了一个整数型的常量 a。常量(constant)意味着一旦给这个变量赋值之后,就不能再改变它的值,所以它必须拥有初始化值。

5. 基类的保护成员在派生类中仍然是保护的。

【答案】错误。在公有派生中,基类的保护成员在派生类中仍然是保护的。

【解析】 在公有派生中,基类的保护成员在派生类中仍是保护的。但在私有派生中,基类的保护成员将变为私有的。

6. 成员的访问能力在私有派生类中和公有派生类中是不同的。

【答案】正确

*【解析】 *在C++中,成员的访问能力在私有派生类和公有派生类中的确存在差异。以下是这两种继承方式下基类成员在派生类中的访问权限:

  1. 公有派生(public inheritance):
    • 基类的公共(public)成员在派生类中保持为公共成员,可以被任何代码访问。
    • 基类的保护(protected)成员在派生类中保持为保护成员,可以被派生类的成员函数、派生类的友元以及进一步的派生类访问,但不能被派生类的对象直接访问。
  2. 私有派生(private inheritance):
    • 基类的公共(public)和保护(protected)成员在派生类中都变为私有(private)成员,只能被派生类的成员函数访问,不能被派生类的对象或派生类的友元访问。
    • 基类的私有(private)成员在派生类中不可见,无法直接访问。

因此,成员的访问能力在私有派生类和公有派生类中是不同的。公有派生主要表示"is-a"(是一个)的关系,意味着派生类是基类的一种类型,可以公开基类的接口。而私有派生则更侧重于实现复用,将基类的实现细节作为派生类的一部分,但不公开基类的接口。在这种情况下,基类的公共和保护成员在派生类中变成了私有成员,限制了外部对这些成员的访问。

7. 派生类只能继承基类的一个构造函数。

【答案】错误。派生类不可以继承基类的构造函数。

【解析】 派生类并不直接继承基类的构造函数。实际上,派生类有自己的构造函数,这些构造函数可以调用基类的构造函数来初始化基类部分。

8. 判断下列语句的正误:int &a=m;

【答案】错误。int m=10; int &a=m;

【解析】 该语句的正误取决于变量 m 的类型和上下文。如果 m 是一个整数变量(例如 int m;),那么这个语句是错误的,因为你不能直接将一个普通变量赋值给一个引用。在C++中,引用必须在声明时初始化,并且必须绑定到一个已经存在的对象或者是一个具有相同类型的临时对象上。正确的用法应该是先定义一个整数变量,然后让引用绑定到这个变量上。

9. 派生类可以有自己的构造函数。

【答案】正确

【解析】 派生类确实可以有自己的构造函数。派生类的构造函数用于初始化派生类自身的成员变量以及通过基类构造函数初始化继承自基类的部分。

10. 要使一个类成为抽象类,这个类至少要有一个虚函数。

【答案】错误。要使一个类成为抽象类,这个类至少要有一个纯虚函数。

【解析】 要使一个类成为抽象类,这个类至少要有一个纯虚函数(virtual function with = 0),而不是任意的虚函数。纯虚函数是在基类中声明并定义为零的虚函数,其目的是为了在派生类中实现该函数。声明纯虚函数的语法是在虚函数声明后加上“= 0”。例如:

class AbstractClass {
public:
    virtual void pureVirtualFunction() = 0; // 纯虚函数
};

包含纯虚函数的类被称为抽象类或接口类。抽象类不能被直接实例化,只能作为其他类的基类来使用。派生类必须提供纯虚函数的实现,否则该派生类也将成为抽象类。

因此,要使一个类成为抽象类,这个类至少要有一个纯虚函数,而不是任意的虚函数。如果类中只有普通的虚函数(没有定义为纯虚函数),那么这个类仍然是一个具体类,可以被实例化。

简答题

1. 请简述什么是构造函数?什么是成员函数?两者的区别在哪里?

【解答】

  • 构造函数:构造函数是一种特殊的成员函数,用来对类中的数据成员作初始化。(2分)
  • 成员函数:类中的一部分,表明对象的行为。(2分)
  • 区别:构造函数是一种特殊的成员函数,函数名就是类名,没有返回值,可以重载,构造函数的调用是在定义对象时有系统直接调用的。成员函数函数名不能是类名,可以有返回值,调用方法与普通函数一样。

2. C++语言中的文件包含语句是指什么?使用时引号和尖括号有什么区别?

【解答】

  • C++中的文件包含语句是指:一个程序把另一个指定文件的内容包含进来。
  • 使用双引号还是尖括号,其含义不一样。
    • 采用尖括号引用系统提供的包含文件,C++ 编译系统将首先在 C++ 语言系统设定的目录中寻找文件,如果没找到,就到指定的目录中去寻找。
    • 采用双引号引用自己定义的包含文件(一般都放在自己指定的目录中),这将通知 C++ 编译器在用户当前目录下或指定的目录下寻找包含文件。

3. 请简述面向对象程序设计的特点。

【解答】面向对象程序设计具有:类和对象(抽象)封装继承多态性等关键要素。

  • 抽象是一种从一般的观点看待事物的方法,即集中于事物的本质特征,而不是具体细节或具体实现。对象是类的具体化,类时对象的抽象。
  • 封装是为了保护类的安全性,将数据成员和成员函数封装在一起,尽可能隐蔽对象的内部细节。
  • 继承是一个类可以获得另一个类的特性的机制。
  • 多态性是指不同的对象可以调用相同名称的函数,但可导致完全不同的行为的现象。

4.如果输入为 8, 5;请写出下列程序的运行结果。

#include <iostream>
using namespace std; 

int max(int,int);
void main()
{
    int a,b,c;
    cin>>a>>b;
    c=max(a,b);
    cout<<“max=”<<c<<endl;
}
int max(int x,int y)
{ 
    int z;
    if(x>y) z=x;
    else z=y;
    return(z);
}

【答案】

max=8

【考点】函数调用

【解析】 该程序首先包含了 <iostream> 头文件,并使用 std 命名空间。程序定义了一个名为 max 的函数,该函数接受两个整数参数 xy,并返回它们中的较大值。

main 函数中,程序从用户那里读取两个整数 ab,然后调用 max 函数来找到这两个数中的最大值,并将结果存储在变量 c 中。最后,程序输出 "max=" 后跟最大值 c

当输入为 8, 5 时,程序会将 a 赋值为 8,将 b 赋值为 5。然后调用 max(8, 5),由于 8 大于 5,所以 max 函数返回 8

5. 请写出以下程序的运行结果。

#include <iostream>
using namespace std;

int gun(int x,int y)
{
    static int m=0,i=2;
    i=m+1; // 7
    m=i+x+y; // 7+4+1
    return m;
}
main()
{
    int j=4,m=1,k;
    k=gun(j,m);
    cout<<k<<endl;
    k=gun(j,m); 
    cout<<k<<endl;
}

【答案】

6
12

【考点】静态变量

【解析】 该程序中定义了一个名为 gun 的函数,该函数接受两个整数参数 xy。在函数内部,有两个静态变量 mi。静态变量在函数的生命周期内保持其值,即在多次调用函数之间保留其值。

函数首先更新 i 的值为 m+1,然后更新 m 的值为 i+x+y,最后返回 m 的值。

main 函数中,首先定义了两个整数变量 jm,并分别赋值为 41。接着调用 gun 函数两次,并将结果存储在变量 k 中,然后输出 k 的值。

第一次调用 gun(j, m) 时,静态变量 mi 的初值均为 0。因此,i 被更新为 1m 被更新为 1+4+1=6。函数返回 m 的值 6,并输出。

第二次调用 gun(j, m) 时,由于 mi 是静态变量,它们保留了上一次调用后的值,即 m=6i=1。因此,i 被更新为 m+17m 被更新为 7+4+1=12。函数返回 m 的值 12,并输出。

  • 23
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Loyreau

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值