本文由 OOP 课程 HW1–HW6 的个人 TeX 错题笔记整理而成。每道题均保留原题、选项和代码;答案与解析以原笔记为基础,并保留其中对题库表述不严谨之处的辨析。
题干、选项和代码默认展示,答案与解析折叠在题目下方。部分题目带有 Java/C# 或旧教材语境,阅读时应以题目所指定的语言和标准为准。
校勘说明
- HW1 Question 8 的原题不是严格的单选题:按照 C++ 语言规则,B、C、D 都可以判为错误陈述;题库预期答案应是 B。
- “C++ 完全向下兼容 C”是常见但不严谨的说法。两者具有很高的源码兼容性,但 C++ 不是 C 的严格超集。
- 涉及拷贝构造的题目默认采用课程基础语境;现代 C++ 还需要考虑移动构造和复制消除。
- 原笔记中的题库答案予以保留;遇到题干或选项存在歧义时,解析会优先说明标准 C++ 下的严格结论。
阅读索引
- HW1:OOP 基础、抽象、封装与命名空间
- HW2:对象、构造/析构、成员、友元与运算符
- HW3:继承、访问控制与类型转换
- HW4:多态、虚函数与抽象类
- HW5:综合代码题与进阶专题
- HW6:模板、STL、字符串与异常处理
HW1
C++ OOP and Namespaces Questions
Which concept of OOP is false for C++?
A. Code can be written without using classes
B. Code must contain at least one class
C. A class must have member functions
D. At least one object should be declared in code
查看答案与解析
答案:B
**解析:**正确选项是 B。C++ 是一门多范式(Multi-paradigm)语言。它不仅支持面向对象,还完全向下兼容 C 语言的面向过程编程。你可以写一个只有 main() 函数和几个普通计算程序的 .cpp 文件,里面不定义任何类,代码依然能完美编译和运行。因此,“代码必须包含类”这个说法在 C++ 中是绝对错误的。
Which feature allows open recursion, among the following?
A. Use of this pointer
B. Use of pointers
C. Use of pass by value
D. Use of parameterized constructor
查看答案与解析
答案:A
**解析:**正确选项是 A。“开放递归(Open Recursion)”是面向对象中的一个术语,指的是在类的内部,一个成员函数去调用另一个成员函数。在 C++ 编译器底层,这种类内部的函数相互调用,实际上都是通过隐藏的 this 指针(例如隐式执行了 this->anotherFunction())来完成的。这也是实现多态时,基类调用虚函数能正确路由到子类实现的关键机制。
Which among the following is false, for a member function of a class?
A. All member functions must be defined
B. Member functions can be defined inside or outside the class body
C. Member functions need not be declared inside the class definition
D. Member functions can be made friend to another class using the friend keyword
查看答案与解析
答案:C
解析:正确选项是 C。C++ 的语法严格要求,类的所有行为规范必须在类的 \{\} 内部声明清楚。你可以把成员函数的具体实现(函数体)写在类的外面(使用作用域解析符 ClassName::),但你必须在类的大括号里面先写上它的声明(函数原型)。如果不声明,编译器将无法识别该函数属于这个类。
Abstraction principle includes____
A. Use abstraction at its minimum
B. Use abstraction to avoid longer codes
C. Use abstraction whenever possible to avoid duplication
D. Use abstraction whenever possible to achieve OOP
查看答案与解析
答案:C
**解析:**正确选项是 C。抽象的核心目的不仅是隐藏细节,更是为了提炼共性。当你的代码中出现多处类似的逻辑时,软件工程的 DRY (Don’t Repeat Yourself) 原则建议你将这些重复的部分“抽象”成一个公共的函数、类或基类。这能大幅提高代码的复用性和可维护性。
Encapsulation and abstraction differ as ____
A. Binding and Hiding respectively
B. Hiding and Binding respectively
C. Can be used any way
D. Hiding and hiding respectively
查看答案与解析
答案:A
解析:正确选项是 A。这是一道非常经典的区分题:封装(Encapsulation)侧重于绑定(Binding),它把数据(属性)和操作数据的方法捆绑成一个不可分割的整体;而抽象(Abstraction)侧重于隐藏(Hiding),它向外界隐藏内部复杂的运作机制,只暴露出最简单、必要的接口。
In terms of stream and files ____
A. Abstraction is called a stream and device is called a file
B. Abstraction is called a file and device is called a stream
C. Abstraction can be called both file and stream
D. Abstraction can’t be defined in terms of files and stream
查看答案与解析
答案:A
解析:正确选项是 A。在 C++ 的 I/O 系统中,“流(Stream)”是一个纯粹的逻辑抽象概念,代表数据的流动过程(如 cin, cout)。而“文件(File)”或者显示器、键盘等,则是具体存在的物理设备(Device)。我们通过操作“流”这个抽象层,来实现对物理设备的统一数据读写。
Which among the following is not a level of abstraction?
A. Logical level
B. Physical level
C. View level
D. External level
查看答案与解析
答案:D
**解析:**正确选项是 D。这道题的背景源自计算机科学中经典的数据抽象三层架构:1. 物理层(Physical level):数据在底层的实际存储方式;2. 逻辑层(Logical level):数据的结构与关系;3. 视图层(View level):用户界面上展示的特定数据子集。“External level(外部层)”通常在数据库领域的某些特定标准中作为 View level 的同义词,但在这种标准的三层架构单选题中,它被视为非标准层级或干扰项。
Identify the correct statement.
A. Namespace is used to group class, objects and functions
B. Namespace is used to mark the beginning of the program
C. A namespace is used to separate the class, objects
D. Namespace is used to mark the beginning & end of the program
查看答案与解析
答案:A
**解析:**正确选项是 A。命名空间(Namespace)的作用类似于文件系统中的“文件夹”。在大型工程中,为了防止不同的模块产生命名冲突(Name Collision),我们使用命名空间将相关的类、对象、变量和函数包裹并分组在一起,实现隔离和管理。
What is the use of Namespace?
A. To encapsulate the data
B. To structure a program into logical units
C. Encapsulate the data & structure a program into logical units
D. It is used to mark the beginning of the program
查看答案与解析
答案:B
**解析:**正确选项是 B。这与第 40 题逻辑一致。类的主要目的是封装数据和方法(Encapsulate the data),而命名空间则是在更高的宏观维度上,将程序的代码架构划分为不同的“逻辑单元”或“模块”(例如 C++ 标准库的所有内容都被组织在 std 这个逻辑单元里)。
What will be the output of the following C++ code?
#include <iostream>
using namespace std;
namespace extra {
int i;
}
void i() {
using namespace extra;
int i;
i = 9;
cout << i;
}
int main() {
enum letter { i, j };
class i { letter j; };
::i();
return 0;
}
A. 9
B. 10
C. compile time error
D. 11
查看答案与解析
答案:A
**解析:**正确选项是 A。这道题考察的是作用域解析和变量覆盖(Shadowing)。在 main 函数中,::i() 前面的 :: 告诉编译器忽略局部作用域里的枚举 i 和类 i,直接调用全局函数 void i()。在函数 i() 内部,虽然引入了 extra 命名空间,但紧接着声明的局部变量 int i; 优先级更高,直接屏蔽(Shadow)了命名空间里的 i。因此,i = 9 修改的是局部变量,最终输出 9。
What will be the output of the following C++ code?
#include <iostream>
using namespace std;
namespace {
int var = 10;
}
int main() {
cout << var;
}
A. 10
B. Error
C. Some garbage value
D. Nothing but program runs perfectly
查看答案与解析
答案:A
解析:正确选项是 A。代码中使用的是匿名命名空间(Unnamed Namespace)。匿名命名空间中的变量和函数自动具有内部链接属性(类似于 static 全局变量),它们的作用域被严格限制在当前文件中。在当前文件的 main() 函数中,可以直接通过变量名 var 访问它而无需任何前缀,因此程序正常输出 10。
HW2
PTA2
The copy constructors can be used to ____
A. Copy an object so that it can be passed to another primitive type variable
B. Copy an object for type casting
C. Copy an object so that it can be passed to a function
D. Copy an object so that it can be passed to a class
查看答案与解析
答案:C
**解析:**正确选项是 C。当对象以“值传递(Pass by Value)”的方式作为形参传入函数,或者从函数中按值返回时,编译器会自动调用拷贝构造函数(Copy Constructor)来生成该对象的一个克隆副本,以避免原始对象的数据被函数内部意外破坏。
Which constructor will be called from the object obj2 in the following C++ program?
A obj2(10,20);
A. A(int y, int x)
B. A(int y; int x)
C. A(int y)
D. A(int x)
查看答案与解析
答案:A
**解析:**正确选项是 A。对象实例化时,编译器会根据传入参数的数量、类型和顺序进行函数重载决议(Overload Resolution)。obj2 在创建时明确传入了两个整型参数 (10, 20),因此精确匹配带有两个 int 形参的构造函数 A(int y, int x)。
Which of the following is not a property of an object?
A. Properties
B. Names
C. Identity
D. Attributes
查看答案与解析
答案:B
**解析:**正确选项是 B。在面向对象编程(OOP)理论中,对象包含三个核心要素:状态(State / Properties / Attributes)、行为(Behavior / Methods)和标识(Identity,例如内存地址)。“名字(Names)”仅仅是代码中程序员用于引用该对象的变量标识符,它不是对象本身固有的、独立于程序运行的内在属性。
If data members are private, what can we do to access them from the class object?
A. Private data members can never be accessed from outside the class
B. Create public member functions to access those data members
C. Create private member functions to access those data members
D. Create protected member functions to access those data members
查看答案与解析
答案:B
**解析:**正确选项是 B。这是面向对象“封装(Encapsulation)”特性的标准实践:将数据成员设为 private 隐藏在类内部,同时暴露 public 的成员函数(如常见的 Getter 和 Setter 方法)作为合法接口,供外部代码安全地读取和修改这些数据。
Copy constructor will be called whenever the compiler ____
A. Generates implicit code
B. Generates member function calls
C. Generates temporary object
D. Generates object operations
查看答案与解析
答案:C
**解析:**正确选项是 C。C++ 编译器在底层处理对象的按值传参、按值返回,或者执行某些隐式类型转换时,通常会在内存的栈区生成临时对象(Temporary object)。每当这个临时对象被创建并需要用另一个现存对象来初始化时,就必定会触发拷贝构造函数的调用。
Can a copy constructor be made private?
A. Yes, always
B. Yes, if no other constructor is defined
C. No, never
D. No, private members can’t be accessed
查看答案与解析
答案:A
**解析:**正确选项是 A。在 C++ 中(尤其是 C++11 标准之前),将拷贝构造函数和赋值运算符显式声明为 private 且不提供实现,是一种极其经典的防止对象被错误复制的模式(即打造 Non-copyable Object,如互斥锁、单例对象等)。如今虽更推荐使用 = delete,但将其设为私有在语法上永远是合法的。
Does constructor overloading include different return types for constructors to be overloaded?
A. Yes, if return types are different, signature becomes different
B. Yes, because return types can differentiate two functions
C. No, return type can’t differentiate two functions
D. No, constructors doesn’t have any return type
查看答案与解析
答案:D
**解析:**正确选项是 D。构造函数是一种极其特殊的成员函数,它在语法上根本不允许定义任何返回类型(连 void 都不允许写)。因此,既然没有返回类型,自然也就谈不上“依靠返回类型的不同来进行重载”。构造函数的重载只能通过参数列表(形参类型、个数、顺序)的不同来实现。
Destructor calls ____ (C++)
A. Are only implicit
B. Are only explicit
C. Can be implicit or explicit
D. Are made at end of program only
查看答案与解析
答案:C
解析:正确选项是 C。析构函数通常在对象离开其作用域或生命周期结束时,由系统隐式调用(Implicit)。但在某些高级内存管理场景下(例如使用了定位 new / Placement new 在预分配的内存上构造对象时),程序员必须通过 obj. ClassName() 的语法来**显式调用(Explicit)**析构函数以清理资源。
When a destructor is called?
A. After the end of object life
B. Anytime in between object’s lifespan
C. At end of whole program
D. Just before the end of object life
查看答案与解析
答案:D
**解析:**正确选项是 D。析构函数的调用时机非常精确:它是在对象的生命周期即将终结,但其所占用的内存空间还未被系统彻底回收的“最后一刻(Just before)”被执行。它的核心任务是在对象彻底灰飞烟灭前,安全地释放掉它生前持有的外部资源(如堆内存、文件句柄等)。
Global destructors execute in ____ order after main function is terminated.
A. Sequential
B. Random
C. Reverse
D. Depending on priority
查看答案与解析
答案:C
解析:正确选项是 C。C++ 中对象的构造和析构遵循栈(Stack)的“后进先出(LIFO)”严格逻辑。因此,无论是在局部函数中还是在全局存储区,对象的析构顺序总是与其在初始化时构造的顺序完全相反(Reverse order)。
Which among the following is true for public class?
A. There can be more than one public class in a single program
B. Public class members can be used without using instance of class
C. Public class is available only within the package
D. Public classes can be accessed from any other class using instance
查看答案与解析
答案:D
**解析:**正确选项是 D。(注:这道题干带有强烈的 Java/C# 面向对象风格)。公开类(Public Class)的设计初衷就是向整个程序的其他模块暴露其定义。在任何其他类或作用域中,只要你创建了该公开类的实例(Instance/对象),就可以自由地访问其公共属性和方法。
What is the output of following code?
int n=10; // global
class A {
private :
int n;
public :
int m;
A() { n=100; m=50; }
void disp() { cout<<"n"<<m<<n; }
};
A. 1050100
B. 1005010
C. n5010
D. n50100
查看答案与解析
答案:D
解析:正确选项是 D。本题考查名字查找和局部优先原则。在 disp() 的输出流中:第一个 "n" 是带有双引号的字符串字面量,原样输出字符 n;接着输出 m 的值 50;最后输出变量 n。根据 C++ 的局部优先原则(Name Shadowing/Hiding),类内部的成员变量 n=100 的作用域覆盖了全局变量 n=10。因此最终拼接的输出结果为 n50100。
Can a function, other than the enclosing function of local class, access the class members?
A. Yes, using object
B. Yes, using direct call
C. Yes, using pointer
D. No, can’t access
查看答案与解析
答案:D
**解析:**正确选项是 D。局部类(Local Class)是定义在某一个特定函数体内部的类。它的作用域被死死限制在包裹它的那个函数的花括号内,对外部世界完全隔离(作用类似于局部变量)。因此,定义它的外部函数之外的其他任何函数,甚至连它的名字都无法识别,更别提访问其成员了。
Which among the following is the main advantage of using local classes?
A. Make program more efficient
B. Makes program execution faster
C. Helps to add extra functionality to a function
D. Helps to add more members to a function
查看答案与解析
答案:C
**解析:**正确选项是 C。局部类并不能提升程序的运行速度或效率。它的核心价值在于代码结构的管理:当你编写一个复杂的函数时,可以临时在内部定义一个小型的辅助数据结构,用来提供该函数专属的额外功能。这能完美避免污染全局的命名空间,极大地提高了代码的内聚性和可读性。
Non-static nested classes have access to ____ from enclosing class.
A. Private members
B. Protected members
C. Public members
D. All the members
查看答案与解析
答案:D
解析:正确选项是 D。在 C++ 访问控制规则中,嵌套类(Nested Class)被编译器完全视同为外部类的一个内部成员。由于“成员可以访问本类的所有其他成员”,因此嵌套类享有极高的权限,它可以无条件访问包围它的外部类的所有成员(包括 private 和 protected 成员)。
Which among the following is correct?
A. Friend function of derived class can access non-private members of base class
B. Friend function of base class can access derived class members
C. Friend function of derived class can access members of only derived class
D. Friend function can access private members of base class of a derived class
查看答案与解析
答案:A
**解析:**正确选项是 A。友元关系是不具备继承性的。子类(派生类)的友元函数可以访问子类的所有成员;而父类(基类)的非私有成员(public 和 protected)已经被子类成功继承下来,成为了子类自身组成部分。因此,子类的友元函数自然能够顺理成章地访问这些通过继承得来的父类非私有成员。
The copy constructors can be used to ____
A. Copy an object so that it can be passed to another primitive type variable
B. Copy an object for type casting
C. Copy an object so that it can be passed to a function
D. Copy an object so that it can be passed to a class
查看答案与解析
答案:C
**解析:**正确选项是 C。当对象以“值传递(Pass by Value)”的方式作为形参传入函数,或者从函数中按值返回时,编译器会自动调用拷贝构造函数(Copy Constructor)来生成该对象的一个克隆副本,以避免原始对象的数据被函数内部意外破坏。
Which constructor will be called from the object obj2 in the following C++ program?
A obj2(10,20);
A. A(int y, int x)
B. A(int y; int x)
C. A(int y)
D. A(int x)
查看答案与解析
答案:A
**解析:**正确选项是 A。对象实例化时,编译器会根据传入参数的数量、类型和顺序进行函数重载决议(Overload Resolution)。obj2 在创建时明确传入了两个整型参数 (10, 20),因此精确匹配带有两个 int 形参的构造函数 A(int y, int x)。
Which of the following is not a property of an object?
A. Properties
B. Names
C. Identity
D. Attributes
查看答案与解析
答案:B
**解析:**正确选项是 B。在面向对象编程(OOP)理论中,对象包含三个核心要素:状态(State / Properties / Attributes)、行为(Behavior / Methods)和标识(Identity,例如内存地址)。“名字(Names)”仅仅是代码中程序员用于引用该对象的变量标识符,它不是对象本身固有的、独立于程序运行的内在属性。
If data members are private, what can we do to access them from the class object?
A. Private data members can never be accessed from outside the class
B. Create public member functions to access those data members
C. Create private member functions to access those data members
D. Create protected member functions to access those data members
查看答案与解析
答案:B
**解析:**正确选项是 B。这是面向对象“封装(Encapsulation)”特性的标准实践:将数据成员设为 private 隐藏在类内部,同时暴露 public 的成员函数(如常见的 Getter 和 Setter 方法)作为合法接口,供外部代码安全地读取和修改这些数据。
Copy constructor will be called whenever the compiler ____
A. Generates implicit code
B. Generates member function calls
C. Generates temporary object
D. Generates object operations
查看答案与解析
答案:C
**解析:**正确选项是 C。C++ 编译器在底层处理对象的按值传参、按值返回,或者执行某些隐式类型转换时,通常会在内存的栈区生成临时对象(Temporary object)。每当这个临时对象被创建并需要用另一个现存对象来初始化时,就必定会触发拷贝构造函数的调用。
Can a copy constructor be made private?
A. Yes, always
B. Yes, if no other constructor is defined
C. No, never
D. No, private members can’t be accessed
查看答案与解析
答案:A
**解析:**正确选项是 A。在 C++ 中(尤其是 C++11 标准之前),将拷贝构造函数和赋值运算符显式声明为 private 且不提供实现,是一种极其经典的防止对象被错误复制的模式(即打造 Non-copyable Object,如互斥锁、单例对象等)。如今虽更推荐使用 = delete,但将其设为私有在语法上永远是合法的。
Does constructor overloading include different return types for constructors to be overloaded?
A. Yes, if return types are different, signature becomes different
B. Yes, because return types can differentiate two functions
C. No, return type can’t differentiate two functions
D. No, constructors doesn’t have any return type
查看答案与解析
答案:D
**解析:**正确选项是 D。构造函数是一种极其特殊的成员函数,它在语法上根本不允许定义任何返回类型(连 void 都不允许写)。因此,既然没有返回类型,自然也就谈不上“依靠返回类型的不同来进行重载”。构造函数的重载只能通过参数列表(形参类型、个数、顺序)的不同来实现。
Destructor calls ____ (C++)
A. Are only implicit
B. Are only explicit
C. Can be implicit or explicit
D. Are made at end of program only
查看答案与解析
答案:C
解析:正确选项是 C。析构函数通常在对象离开其作用域或生命周期结束时,由系统隐式调用(Implicit)。但在某些高级内存管理场景下(例如使用了定位 new / Placement new 在预分配的内存上构造对象时),程序员必须通过 obj. ClassName() 的语法来**显式调用(Explicit)**析构函数以清理资源。
When a destructor is called?
A. After the end of object life
B. Anytime in between object’s lifespan
C. At end of whole program
D. Just before the end of object life
查看答案与解析
答案:D
**解析:**正确选项是 D。析构函数的调用时机非常精确:它是在对象的生命周期即将终结,但其所占用的内存空间还未被系统彻底回收的“最后一刻(Just before)”被执行。它的核心任务是在对象彻底灰飞烟灭前,安全地释放掉它生前持有的外部资源(如堆内存、文件句柄等)。
Global destructors execute in ____ order after main function is terminated.
A. Sequential
B. Random
C. Reverse
D. Depending on priority
查看答案与解析
答案:C
解析:正确选项是 C。C++ 中对象的构造和析构遵循栈(Stack)的“后进先出(LIFO)”严格逻辑。因此,无论是在局部函数中还是在全局存储区,对象的析构顺序总是与其在初始化时构造的顺序完全相反(Reverse order)。
Which among the following is true for public class?
A. There can be more than one public class in a single program
B. Public class members can be used without using instance of class
C. Public class is available only within the package
D. Public classes can be accessed from any other class using instance
查看答案与解析
答案:D
**解析:**正确选项是 D。(注:这道题干带有强烈的 Java/C# 面向对象风格)。公开类(Public Class)的设计初衷就是向整个程序的其他模块暴露其定义。在任何其他类或作用域中,只要你创建了该公开类的实例(Instance/对象),就可以自由地访问其公共属性和方法。
What is the output of following code?
int n=10; // global
class A {
private :
int n;
public :
int m;
A() { n=100; m=50; }
void disp() { cout<<"n"<<m<<n; }
};
A. 1050100
B. 1005010
C. n5010
D. n50100
查看答案与解析
答案:D
解析:正确选项是 D。本题考查名字查找和局部优先原则。在 disp() 的输出流中:第一个 "n" 是带有双引号的字符串字面量,原样输出字符 n;接着输出 m 的值 50;最后输出变量 n。根据 C++ 的局部优先原则(Name Shadowing/Hiding),类内部的成员变量 n=100 的作用域覆盖了全局变量 n=10。因此最终拼接的输出结果为 n50100。
Can a function, other than the enclosing function of local class, access the class members?
A. Yes, using object
B. Yes, using direct call
C. Yes, using pointer
D. No, can’t access
查看答案与解析
答案:D
**解析:**正确选项是 D。局部类(Local Class)是定义在某一个特定函数体内部的类。它的作用域被死死限制在包裹它的那个函数的花括号内,对外部世界完全隔离(作用类似于局部变量)。因此,定义它的外部函数之外的其他任何函数,甚至连它的名字都无法识别,更别提访问其成员了。
Which among the following is the main advantage of using local classes?
A. Make program more efficient
B. Makes program execution faster
C. Helps to add extra functionality to a function
D. Helps to add more members to a function
查看答案与解析
答案:C
**解析:**正确选项是 C。局部类并不能提升程序的运行速度或效率。它的核心价值在于代码结构的管理:当你编写一个复杂的函数时,可以临时在内部定义一个小型的辅助数据结构,用来提供该函数专属的额外功能。这能完美避免污染全局的命名空间,极大地提高了代码的内聚性和可读性。
Non-static nested classes have access to ____ from enclosing class.
A. Private members
B. Protected members
C. Public members
D. All the members
查看答案与解析
答案:D
解析:正确选项是 D。在 C++ 访问控制规则中,嵌套类(Nested Class)被编译器完全视同为外部类的一个内部成员。由于“成员可以访问本类的所有其他成员”,因此嵌套类享有极高的权限,它可以无条件访问包围它的外部类的所有成员(包括 private 和 protected 成员)。
Which among the following is correct?
A. Friend function of derived class can access non-private members of base class
B. Friend function of base class can access derived class members
C. Friend function of derived class can access members of only derived class
D. Friend function can access private members of base class of a derived class
查看答案与解析
答案:A
**解析:**正确选项是 A。友元关系是不具备继承性的。子类(派生类)的友元函数可以访问子类的所有成员;而父类(基类)的非私有成员(public 和 protected)已经被子类成功继承下来,成为了子类自身组成部分。因此,子类的友元函数自然能够顺理成章地访问这些通过继承得来的父类非私有成员。
What are the constant member functions?
A. Functions which doesn’t change value of calling object
B. Functions which doesn’t change value of any object inside definition
C. Functions which doesn’t allow modification of any object of class
D. Functions which doesn’t allow modification of argument objects
查看答案与解析
答案:A
**解析:**正确选项是 A。常成员函数(即在函数声明末尾加上 const 关键字的函数,例如 void func() const;)是在向编译器郑重承诺:该函数内部绝不会修改调用该对象(即隐含的 this 指针所指向的对象)的任何数据成员状态。它是 C++ 保障数据安全的重要手段。
Which type of member functions get inherited in the same specifier in which the inheritance is done?
A. Private member functions
B. Protected member functions
C. Public member functions
D. All member functions
查看答案与解析
答案:C
**解析:**正确选项是 C。这考查的是 C++ 继承权限修饰符的核心规律:无论哪种继承方式,父类的 private 成员在子类中永远不可见。而父类的 public 成员在继承后,其在子类中的最终权限完全由继承方式(specifier)决定——public 继承依然是 public,protected 继承变成 protected,private 继承变成 private。
If static data members have to be used inside a class, those member functions ____ (when no object exists)
A. Must not be static member functions
B. Must not be member functions
C. Must be static member functions
D. Must not be member function of corresponding class
查看答案与解析
答案:C
**解析:**正确选项是 C。静态数据成员的生命周期独立于任何对象,程序一开始就存在。如果在尚未实例化任何对象的情况下,想要在类内部操作这些静态数据,就必须借助静态成员函数。因为普通成员函数必须依赖对象(需要隐含的 this 指针)才能被调用。
If object of class are created, then the static data members can be accessed ____
A. Using dot operator
B. Using arrow operator
C. Using colon
D. Using dot or arrow operator
查看答案与解析
答案:D
**解析:**正确选项是 D。虽然静态成员属于整个类,业界最规范的推荐写法是使用作用域解析符 ClassName:: 访问。但在 C++ 语法设计中,为了方便和兼容,如果你已经持有了该类的对象实例或对象指针,同样完全允许使用普通的点(.)操作符或指针的箭头(->)操作符去访问静态成员。
Which among the following is wrong syntax related to static data members?
A. className :: staticDataMember;
B. dataType className :: memberName =value;
C. static dataType memberName;
D. className : dataType -> memberName;
查看答案与解析
答案:D
**解析:**正确选项是 D。这是一个明显的“生造”干扰项。合法的静态成员访问语法必须使用双冒号 ::。绝不可能出现单独一个冒号 : 并且诡异地和指针操作符 -> 混用的语法结构。
Which among the following is correct definition for static member functions?
A. Functions created to allocate constant values to each object
B. Functions made to maintain single copy of member functions for all objects
C. Functions created to define the static members
D. Functions made to manipulate static programs
查看答案与解析
答案:B
**解析:**正确选项是 B。注意:在底层物理内存上,无论是普通函数还是静态函数,所有对象的函数代码本来就只有一份。然而,这是各大考研/计算机基础题库中的经典题:出题人意在强调静态函数体现了“大家共有、不属于某一个具体对象”的特性。它属于整个类的抽象级别(Class-level),是独立于具体实例的单一公共方法。
The keyword static is used ____
A. With declaration inside class and with definition outside the class
B. With declaration inside class and not with definition outside the class
C. With declaration and definition wherever done
D. With each call to the member function
查看答案与解析
答案:B
**解析:**正确选项是 B。这是 C++ 的硬性语法规定。当你在类的外部去单独实现(定义)一个静态成员(无论是静态数据变量的内存分配,还是静态函数的实现)时,绝对不能在前面再加 static 关键字,否则会导致链接错误。static 只能出现在类内部的声明处。
What will be the output if all necessary code is included?
void test (Object &y) { y = "It is a string"; }
void main() {
Object x ;
test (x);
cout<<x;
}
A. Run time error
B. Compile time error
C. Null
D. It is a string
查看答案与解析
答案:D
**解析:**正确选项是 D。在 test 函数中,形参使用的是对象的引用(Object &y)。按引用传递意味着 y 只是外部对象 x 的一个别名。因此,在函数内部对 y 进行赋值,本质上直接覆写了外部 x 的内存数据。最终输出修改后的字符串。
Which error will be produced if a local object is returned by reference outside a function?
A. Out of memory error
B. Run time error
C. Compile time error
D. No error
查看答案与解析
答案:B
**解析:**正确选项是 B。这是一个非常致命且经典的“悬空引用(Dangling Reference)”错误。局部对象存在于函数的栈内存中,一旦函数执行结束,这块内存立刻被系统回收。如果返回了它的引用,外部调用者将拿到一个“指向已销毁内存”的毒指针,对其访问极易导致 Segmentation fault 等运行时崩溃(Run time error)。
Can we return an array of objects?
A. Yes, always
B. Yes, only if objects are having same values
C. No, because objects contain many other values
D. No, because objects are single entity (arrays are not a single entity)
查看答案与解析
答案:D
**解析:**正确选项是 D。在 C/C++ 底层机制中,原生数组(Native Array)不支持整体按值复制,因此不能作为函数的返回值直接返回。如果要返回一组数据,我们只能返回指向数组首元素的指针,或者更现代的做法是使用 std::vector 或 std::array 将数组包装为单一的对象实体后再返回。
Which among the following is true?
A. Two objects can point to the same memory location
B. Two objects can never point to the same memory location
C. Objects not allowed to point at a location already occupied
D. Objects can’t point to any address
查看答案与解析
答案:A
**解析:**正确选项是 A。通过指针操作或引用传递,C++ 完全允许让不同的对象(或指针对象)指向堆区或栈区中的同一块物理内存地址。这也是导致“浅拷贝引发内存重复释放(Double Free)”这一经典 Bug 的根本原因。
How the argument passed to a function get initialized?
A. Assigned using copy constructor at time of passing
B. Copied directly
C. Uses addresses always
D. Doesn’t get initialized
查看答案与解析
答案:A
**解析:**正确选项是 A。当对象作为参数进行“按值传递(Pass by Value)”时,系统绝不是简单粗暴地做底层字节复制。相反,系统在开辟函数栈区时,会正规地调用该类的“拷贝构造函数(Copy Constructor)”来精心构建并初始化这个局部的形参对象。
In copy constructor definition, if non const values are accepted only ____
A. Only const objects will be accepted
B. Only non – const objects are accepted
C. Only const members will not get copied
D. Compiler generates an error
查看答案与解析
答案:B
解析:正确选项是 B。拷贝构造函数的参数通常会写成 const ClassName&。如果你没有加 const 修饰(即 ClassName(ClassName& obj)),这就表示你的函数具有修改源对象的潜力。此时,编译器基于类型安全,将绝对不允许你把一个只读的 const 对象传给它。因此它变得只能接受非常量对象(non-const objects)。
Use of assignment operator ____
A. Changes its use, when used at declaration and in normal assignment
B. Doesn’t changes its use, whatever the syntax might be
C. Assignment takes place in declaration and assignment syntax
D. Doesn’t work in normal syntax, but only with declaration
查看答案与解析
答案:A
解析:正确选项是 A。赋值符号 = 在 C++ 中扮演双重角色,根据上下文改变其底层行为:如果在对象刚刚声明创建时使用(例如 A obj2 = obj1;),它实际上调用的是拷贝构造函数;如果在对象早已创建完毕之后的某个语句中使用(例如 obj2 = obj1;),它调用的则是重载的赋值运算符 (operator=)。
Which among the following is true?
A. We can use direct assignment for any object
B. We can use direct assignment only for different class objects
C. We must not use direct assignment
D. We can use direct assignment to same class objects
查看答案与解析
答案:D
**解析:**正确选项是 D。在 C++ 中,即使你没有手动编写任何赋值逻辑,编译器也会自动为每一个类隐式生成一个默认的赋值运算符重载。这意味着,只要属于相同的类,这两个不同实例对象之间就可以直接使用等于号(=)进行互相赋值(默认执行逐成员的浅拷贝)。
What is the size of an object pointer?
A. Equal to size of any usual pointer
B. Equal to size of sum of all the members of object
C. Equal to size of maximum sized member of object
D. Equal to size of void
查看答案与解析
答案:A
**解析:**正确选项是 A。无论一个类包含多少成员,无论该类的实例对象占用多庞大的内存空间,指向该对象的指针仅仅是一个存放内存地址的变量。因此,对象指针的大小永远等于当前计算机架构下普通指针的大小(例如 32 位操作系统下为 4 字节,64 位系统下为 8 字节)。
An object’s this pointer ____
A. Isn’t part of class
B. Isn’t part of program
C. Isn’t part of compiler
D. Isn’t part of object itself
查看答案与解析
答案:D
解析:正确选项是 D。this 指针的本质是编译器在调用类的非静态成员函数时,在幕后隐式传递的第一个函数参数(用于告诉函数当前是在操作哪一个对象)。它根本不存储在对象的物理内存布局中。因此对对象执行 sizeof(),其结果绝对不包含 this 指针的体积。
Which is the correct interpretation of the member function call from an object, object.function(parameter);
A. object.function(&this, parameter)
B. object(&function,parameter)
C. function(&object,¶meter)
D. function(&object,parameter)
查看答案与解析
答案:D
**解析:**正确选项是 D。这是 C++ 面向对象机制最底层的真相:在编译器眼中,其实根本没有所谓的“成员函数”。当你在代码里写出 object.function(arg) 时,编译器在底层会将其重写并转化为普通的全局函数调用:function(&object, arg)。它悄悄地把调用者的内存地址(即 &object)作为第一个隐藏参数传了进去,这个隐藏参数在函数内部接收的名字,就叫做 this 指针。
Which among the following is true? (About this pointer)
A. This pointer can be used to guard against any kind of reference
B. This pointer can be used to guard against self-reference
C. This pointer can be used to guard from other pointers
D. This pointer can be used to guard from parameter referencing
查看答案与解析
答案:B
**解析:**正确选项是 B。在重载赋值运算符(operator=)时,我们必须要防范一种极度危险的操作:“自我赋值(Self-assignment)”,比如 obj = obj;。因为赋值操作通常会先释放自己原有的旧内存,如果是自我赋值,就会把自己的新数据也连同销毁。因此,标准的做法是利用 this 指针进行防御性检查:if (this != &other) \{ ... \}。
This pointer can be used directly to ____
A. To manipulate self-referential data structures
B. To manipulate any reference to pointers to member functions
C. To manipulate class references
D. To manipulate and disable any use of pointers
查看答案与解析
答案:A
**解析:**正确选项是 A。this 指针最常见的直接运用之一,就是在成员函数末尾返回 *this。这使得该函数返回了当前对象本身的引用,从而允许程序员像拼图一样进行极其优雅的“链式调用(Method Chaining)”,例如:obj.setX(1).setY(2).print();。
Which is the correct syntax for declaring the type of this in a member function?
A. classType [cv-qualifier-list] *const this;
B. classType const[cv-qualifier-list] *this;
C.[cv-qualifier-list]*const classType this;
D.[cv-qualifier-list] classType *const this;
查看答案与解析
答案:D
**解析:**正确选项是 D。理解这一点的关键是:this 就像你的身份证,它从你“出生”(进入函数)那一刻起就绑定在你身上,绝对不允许重新指向其他对象。因此,必须将 const 放在 * 号的右边,声明它是一个“常量指针(Constant Pointer)”。若外层函数还有 const 修饰(即 cv-qualifier-list),则指向的数据也会变为不可变。
If a constructors should be capable of creating objects without argument and with arguments, which is a good alternative for this purpose?
A. Use zero argument constructor
B. Use constructor with one parameter
C. Use constructor with all default arguments
D. Use default constructor
查看答案与解析
答案:C
**解析:**正确选项是 C。在 C++ 中,如果我们提供了一个所有参数都带有默认值的构造函数(例如 ClassName(int a = 0, int b = 0);),它就能同时扮演两个角色:当你传参时它是带参构造,当你不传参时它就是无参(默认)构造。这能减少代码冗余。
If the constructors are overloaded by using the default arguments, which problem may arise?
A. The constructors might have all the same arguments except the default arguments
B. The constructors might have same return type
C. The constructors might have same number of arguments
D. The constructors can’t be overloaded with respect to default arguments
查看答案与解析
答案:A
解析:正确选项是 A。滥用带默认参数的构造函数极其容易引发二义性(Ambiguity)冲突。如果类中同时定义了 A() 和 A(int x = 0),当用户编写 A obj; 试图实例化对象时,编译器将彻底精神分裂:它不知道你到底是想调用无参构造函数,还是想调用那个带默认值的函数,最终会导致直接报编译错误。
Which constructor definition will produce a compile time error?
A. className(int x=0);
B. className(char c);
C. className(int x=0, char c);
D. className(char c, int x=0);
查看答案与解析
答案:C
**解析:**正确选项是 C。这是 C++ 形参默认值的铁律:函数的默认参数必须严格遵循“从右向左”连续填充的原则。你绝对不能把一个带有默认值的参数放在一个没有默认值的参数的左边。如果不遵守此规则,编译器在匹配参数时将引发灾难性的混乱。
Which is the correct statement for default constructors?
A. The constructors with all the default arguments
B. The constructors with all the null and zero values
C. The constructors which can’t be defined by programmer
D. The constructors with zero arguments
查看答案与解析
答案:D
解析:正确选项是 D。C++ 标准术语中的“默认构造函数(Default Constructor)”,狭义上就是专指那个不接收任何参数的构造函数(包括你手动写了空参数的,或者所有参数都提供默认值的,或者是编译器自动生成的)。
What happens when new fails?
A. Returns zero always
B. Throws an exception always
C. Either throws an exception or returns zero
D. Terminates the program
查看答案与解析
答案:C
**解析:**正确选项是 C。在现代 C++ 标准中,当堆内存耗尽导致 new 失败时,默认行为是抛出 std::bad_alloc 异常。但如果你使用了特殊的“不抛异常”版本,即 new (std::nothrow) Type;,那么在分配失败时,它就不会抛异常,而是优雅地返回一个空指针 nullptr (即 0)。
If delete is used to delete an object which was not allocated using new ____
A. Then out of memory error arises
B. Then unreachable code error arises
C. Then unpredictable errors may arise
D. Then undefined variable error arises
查看答案与解析
答案:C
**解析:**正确选项是 C。这是一个绝对禁忌的严重错误!new / delete 必须在堆(Heap)内存上成对使用。如果你试图对一个分配在栈(Stack)上或全局数据区的对象地址调用 delete,底层的内存管理器会因找不到合法的堆内存元数据块而崩溃,这在 C++ 中属于典型的未定义行为(Undefined Behavior, UB),会导致难以预测的恐怖后果。
When delete operator is used ____ (If object has a destructor)
A. Object destructor is called after deallocation
B. Object destructor is called before deallocation
C. Object destructor is not used
D. Object destructor can be called anytime during destruction
查看答案与解析
答案:B
解析:正确选项是 B。与 new 操作符相反,delete 的执行过程严格分为两步:第一步,先就地调用对象的析构函数,让对象有尊严地清理掉自己手中的资源;第二步,再调用全局的 operator delete,将这块物理内存彻底交还给操作系统(deallocation)。
If delete is applied to an object whose l-value is modifiable, then ____ after the object is deleted.
A. Its value is defined as null
B. Its value is defined as void
C. Its value is defined as 0
D. Its value is undefined
查看答案与解析
答案:D
**解析:**正确选项是 D。对指针执行 delete 操作,仅仅是把指针指向的那块内存还给了操作系统,它并不会自动把你的指针变量清空为 nullptr。操作结束后,这个指针里仍然保留着原来的物理地址,这就产生了一个极度危险的“悬挂指针(Dangling Pointer)”。任何后续对它的解引用,后果都是未定义(Undefined)的。这也是为什么我们在 delete 之后强烈建议手动写上 ptr = nullptr; 的原因。
Which is the correct syntax to delete an array of objects?
A. delete[] objectName;
B. delete * objectName;
C. objectName[] delete;
D. delete objectName[];
查看答案与解析
答案:A
**解析:**正确选项是 A。使用 new Type[N] 申请的对象数组,在释放时必须配套使用带有方括号的 delete[]。方括号相当于给编译器的一个明显信号:不要只析构第一个元素,请去读取隐藏的数组长度信息,并调用数组中每一个元素的析构函数!若漏掉 [] 会引发严重的内存/资源泄漏。
The delete operator ____
A. Invokes function operator delete
B. Invokes function defined by user to delete
C. Invokes function defined in global scope to delete object
D. Doesn’t invoke any function
查看答案与解析
答案:A
**解析:**正确选项是 A。delete 是 C++ 的一个关键字级别的操作符,它在完成析构后,底层必然会调用配套的 operator delete 函数来实现物理内存的释放。虽然开发者可以重载自己的 operator delete,但若不显式指定,最终也会调用标准库提供的版本。
What are inbuilt classes?
A. The predefined classes in a language
B. The classes that are defined by the user
C. The classes which are meant to be modified by the user
D. The classes which can’t be used by the user
查看答案与解析
答案:A
**解析:**正确选项是 A。“内置类(Inbuilt Classes)”是指由编程语言核心或者标准库预先定义好、开箱即用的类。在 C++ 中,最典型的内置类代表就是标准模板库(STL)中提供的 std::string,以及各类 I/O 流(如 std::istream)。
What doesn’t inbuilt classes contain?
A. Function prototype
B. Function declaration
C. Function definitions
D. Objects
查看答案与解析
答案:D
解析:正确选项是 D。这道题重申了 OOP 的基本哲学理念:类(Class)永远只是描绘蓝图和设计规范的数据结构(里面包含函数声明和定义)。它本身是抽象的,里面绝对不会直接包含实体化的对象(Objects)。对象是运行时通过这份蓝图才被建造出来的。
What is an array of objects?
A. An array of instances of class represented by single name
B. An array of instances of class represented by more than one name
C. An array of instances which have more than 2 instances
D. An array of instances which have different types
查看答案与解析
答案:A
**解析:**正确选项是 A。对象数组本质上就是内存中连续存放的、属于同一个类的多个实例(Instances)。为了方便索引和管理,它们在代码中共享同一个名字(Single name),开发者通过下标(例如 students[0], students[1])来分别定位每个独立的对象。
HW3
Inheritance, Access Specifiers and Object Lifecycle
If class B inherits class A privately. And class B has a friend function. Will the friend function be able to access the private member of class A?
A. Yes, because friend function can access all the members
B. Yes, because friend function is of class B
C. No, because friend function can only access private members of friend class
D. No, because friend function can access private member of class A also
查看答案与解析
答案:C
解析:正确选项是 C。在 C++ 中,友元特权是不继承、不传递的。B 的友元函数只拥有访问 B 自身所有成员的特权。由于 A 的 private 成员对 B 本身都是不可见、被锁死的,B 的友元函数自然也绝对无法“跨越两层”去访问 A 的私有成员。
Which among the following is true for the given code below?
class A {
protected: int marks;
public:
A() { marks=100; }
void disp() { cout<<"marks="<<marks; }
};
class B: protected A { };
B b;
b.disp();
A. Object b can’t access disp() function
B. Object b can access disp() function inside its body
C. Object b can’t access members of class A
D. Program runs fine
查看答案与解析
答案:A
**解析:**正确选项是 A。本题考查继承权限的降级规则。由于使用了 protected 保护继承,基类 A 中原有的 public 接口 disp() 在派生类 B 中被降级成了 protected。受保护成员只对 B 的内部和 B 的子类开放,绝对不允许在外部通过对象(如 b.disp())直接调用,因此引发编译错误。
If a class have default constructor defined in private access, and one parameter constructor in protected mode, how will it be possible to create instance of object?
A. Define a constructor in public access with different signature
B. Directly create the object in the subclass
C. Directly create the object in main() function
D. Not possible
查看答案与解析
答案:D
**解析:**正确选项是 D。构造函数是对象实例化的“唯一大门”。如果所有的构造函数(大门)全部被 private 或 protected 锁死,外部代码(比如 main 函数)就没有任何访问权限,也就绝对不可能(Not possible)直接在外部创建该类的实例(著名的单例模式正是利用这一特性封死外部实例化的)。
Which specifier allows to secure the public members of base class in inherited classes?
A. Private
B. Protected
C. Public
D. Private and Protected
查看答案与解析
答案:D
**解析:**正确选项是 D。
【重点笔记】:在 C++ 面向对象设计的语境中,“secure(保护/确保安全)”通常代表“隐藏外部的访问权限”。
如果你希望基类原本对外敞开的 public 接口,在派生类中变得“安全且不可见”,你应该使用 private 继承或 protected 继承。这两种方式都会将继承来的公有接口降级,从而切断外部对象直接访问的可能。
Which type of inheritance is illustrated by the following code?
class student { public: int marks; };
class topper: public student { public: char grade; };
class average { public: int makrs_needed; };
class section: public average { public: char name[10]; };
class overall: public average { public: int students; };
A. Single level
B. Multilevel and single level
C. Hierarchical
D. Hierarchical and single level
查看答案与解析
答案:D
解析:正确选项是 D。student 派生出 topper 是经典的一对一“单继承(Single level)”;
而 average 像树根一样,同时横向派生出了 section 和 overall 两个平行的分支,这种“一个基类、多个派生类”的结构被称为**“层次继承 / 树状继承(Hierarchical inheritance)”**。
Which type of inheritance results in the diamond problem?
A. Single level
B. Hybrid (部分题库为 Hierarchical & Multiple 的组合)
C. Hierarchical
D. Multilevel
查看答案与解析
答案:B
解析:
**【新概念笔记】:**大名鼎鼎的菱形问题(Diamond Problem)是由 Hybrid(混合继承) 引发的。
什么是混合继承?它其实就是 Hierarchical(层次继承) + Multiple(多重继承)。
例如:爷爷类派生出两个大伯类(这是 Hierarchical);然后孙子类又同时继承这两个大伯类(这是 Multiple)。孙子体内会保留两份爷爷的数据,导致调用时的严重歧义。在题库中通常选 Hybrid,它代表了导致菱形危机的复杂混合结构。
If class A and class B are derived from class C and class D, then ____
A. Those are 2 pairs of single inheritance
B. That is multilevel inheritance
C. Those is enclosing class
D. Those are all independent classes
查看答案与解析
答案:A
**解析:**正确选项是 A。A 继承 C,B 继承 D。这两个继承结构各自为战,互不相干。每一对都完美符合“一个子类对应一个父类”的单继承定义。因此这仅仅是简简单单的 2 对单继承关系。
Single level inheritance supports ____ inheritance.
A. Runtime
B. Compile time
C. Multiple inheritance
D. Language independency
查看答案与解析
答案:B
**解析:正确选项是 B。在 C++ 中,类的继承关系、内存布局大小、以及普通成员函数的绑定,全都是在编译期(Compile time)**就已经严格静态确定的(即使是虚函数表 vtable,其结构的构建也是在编译期完成的,只不过查找动作发生在运行期)。
Which among the following is false for single level inheritance?
A. There can be more than 2 classes in program to implement single inheritance
B. There can be exactly 2 classes to implement single inheritance in a program
C. There can be more than 2 independent classes involved in single inheritance
D. The derived class must implement all the abstract method if single inheritance is used
查看答案与解析
答案:B
**解析:**正确选项是 B。“单继承”仅仅是规范了“认爹的规则(一个派生类只能有一个直接基类)”,但绝不限制程序总体规模。错在“恰好 2 个类(exactly 2 classes)”,一个程序里定义成百上千个类并组成无数对单继承是完全合法的。
Which among the following best defines multilevel inheritance?
A. A class derived from another derived class
B. Classes being derived from other derived classes
C. Continuing single level inheritance
D. Class which have more than one parent
查看答案与解析
答案:A
**解析:**正确选项是 A。多级继承(Multilevel Inheritance)是指一条垂直向下的纵向继承链:基类 \(\rightarrow\) 派生类 \(\rightarrow\) 再派生类。即一个派生类,它是从另一个本来也是派生类的类继承而来的。
In multilevel inheritance one class inherits ____
A. Only one class
B. More than one class
C. At least one class
D. As many classes as required
查看答案与解析
答案:A
**解析:**正确选项是 A。即使是多级继承(A \(\rightarrow\) B \(\rightarrow\) C),你在审查任何一个单独的层级时,它依然只继承了直接上级的一个类(例如 C 的直接基类只有 B)。这和拥有多个直接父类的多重继承(Multiple Inheritance)有本质区别。
Why does diamond problem arise due to multiple inheritance?
A. Methods with same name creates ambiguity and conflict
B. Methods inherited from the superclass may conflict
C. Derived class gets overloaded with more than two class methods
D. Derived class can’t distinguish the owner class of any derived method
查看答案与解析
答案:A
解析:正确选项是 A。菱形问题的核心痛点在于二义性(Ambiguity)。当子类通过多条不同的继承路径,继承了最顶层基类同名的方法或变量时,当你试图调用它,编译器会懵逼:因为存在两条等价的查找路径,编译器无法决断该走哪一条,从而抛出二义性编译错误。
Pointer to a base class can be initialized with the address of derived class, because of ____
A. derived-to-base implicit conversion for pointers
B. base-to-derived implicit conversion for pointers
C. base-to-base implicit conversion for pointers
D. derived-to-derived implicit conversion for pointers
查看答案与解析
答案:A
解析:正确选项是 A。这是 C++ 实现多态的绝对基石,被称为“向上转型(Upcasting)”。因为一个派生类对象在内存布局中必定包含一个完整的基类子对象,所以 C++ 编译器原生且安全地支持将派生类的指针**隐式转换(implicit conversion)**为基类的指针。
Can constructors be overloaded in derived class?
A. Yes, always
B. Yes, if derived class has no constructor
C. No, programmer can’t do it
D. No, never
查看答案与解析
答案:A
**解析:**正确选项是 A。派生类(子类)在行为上也是一个完完全全的标准类。就像普通类一样,只要它的参数列表(类型、数量、顺序)不同,你就可以随心所欲地为派生类重载无数个构造函数。
Is it compulsory for all the classes in multilevel inheritance to have constructors defined explicitly if only last derived class object is created?
A. Yes, always
B. Yes, to initialize the members
C. No, it not necessary
D. No, Constructor must not be define
查看答案与解析
答案:C
**解析:**正确选项是 C。C++ 编译器极其聪明,如果你在继承链的某一层没有手动(显式)定义任何构造函数,编译器会自动为你生成一个“隐式的无参默认构造函数(Implicit default constructor)”。因此,即便继承链很长,也不强制要求(Not compulsory)你给每一个基类都写代码去定义构造函数。
附录:重点知识梳理
C++ 经典继承模式全景对比
在 C++ 面向对象编程与考试中,理清类的派生拓扑结构是解决复杂结构题和“菱形危机”的关键。请牢记以下四种核心继承模式的本质区别:
| 继承模式 (英文) | 拓扑结构 | 核心描述与易错考点 |
|---|---|---|
| Single level (单继承) | 1 对 1 | 一个派生类只拥有唯一一个直接基类。(A \(\rightarrow\) B) **易错点:**单继承约束的只是“认爹的规则”。哪怕程序里写了 1000 个独立的类,只要它们全都是两两一对一继承,整体就依然是单继承。 |
| Multilevel (多级继承) | 单向垂直链 | 派生类作为新的基类,继续派生下一个类,形成家族代代相传的垂直链条。(A \(\rightarrow\) B \(\rightarrow\) C) **易错点:**构造顺序永远从“最顶层的老祖宗”开始往下,析构顺序严格反转(拆楼逻辑)。每层只能看见紧挨着自己的上一层非私有成员。 |
| Hierarchical (层次继承) | 1 对 多 | 一个基类同时派生出多个不同的子类,像大树发叉一样散开。(A \(\rightarrow\) B 且 A \(\rightarrow\) C) **易错点:**兄弟子类之间是平行的,互不干扰。多用于同一基类在不同业务方向上的分支实现。 |
| Hybrid (混合继承) | 网状交织 | 两种或两种以上继承方式的结合体(通常是 Hierarchical 加上 Multiple 多重继承)。 **易错点:**这是导致大名鼎鼎的 菱形问题 (Diamond Problem) 的罪魁祸首!子类通过不同的路径继承了同一个顶层基类的两份数据拷贝,调用时会产生严重的“二义性(Ambiguity)”。 |
【特别补充:Multiple Inheritance (多重继承)】
很多时候题目会单独考察它。它指的是一个子类同时拥有多个直接基类(多对 1,例如 B 和 C 共同派生出 D)。它正是引发上述 Hybrid 混合继承“菱形危机”的核心机制。在 C++ 中,为了解决菱形二义性,必须在多重继承的中间层使用 virtual 关键字进行虚继承 (Virtual Inheritance)。
HW4
Which among the following is mandatory condition for operators overloading?
A. Overloaded operator must be member function of the left operand
B. Overloaded operator must be member function of the right operand
C. Overloaded operator must be member function of either left or right operand
D. Overloaded operator must not be dependent on the operands
查看答案与解析
答案:A
**解析:正确选项是 A。在 C++ 面向对象题库的标准语境中,本题特指“重载为成员函数”**的前提条件。为了让编译器识别重载并隐含传递 this 指针,运算符必须作为表达式左侧操作数的成员函数(即左操作数充当调用函数的对象)。如果是友元函数重载则无此限制,但在该类题库中 A 为标准的预期答案。
When the operator to be overloaded becomes the left operand member then ____
A. The right operand acts as implicit object represented by *this
B. The left operand acts as implicit object represented by *this
C. Either right or left operand acts as implicit object represented by *this
D. *this pointer is not applicable in that member function
查看答案与解析
答案:B
**解析:**正确选项是 B。当二元运算符(如 +)被重载为类的成员函数时,执行 A + B 实际上是被编译器转换为 A.operator+(B)。因此,左操作数(A)成为了隐含的调用对象,在成员函数内部由 *this 指针来代表。
*If the left operand is pointed by this pointer, what happens to other operands?
A. Other operands are passed as function return type
B. Other operands are passed to compiler implicitly
C. Other operands must be passed using another member function
D. Other operands are passed as function arguments
查看答案与解析
答案:D
解析:正确选项是 D。在成员函数形式的二元运算符重载中,因为左操作数已经作为隐含的 *this 指针存在,所以右操作数(即 other operands)必须显式地作为**函数参数(Function arguments)**传递进该成员函数中。例如声明为:ReturnType operator+(const ClassName& right_operand);。
Which object’s members can be called directly while overloading operator function is used (In function definition)?
A. Left operand members
B. Right operand members
C. All operand members
D. None of the members
查看答案与解析
答案:A
解析:正确选项是 A。由于重载的成员函数是由左操作数(即 *this)主动调用的,所以在重载函数的函数体内部,你可以直接访问左操作数的成员变量(例如直接写 val,编译器会自动将其解析为 this->val)。而右操作数的成员不能直接写名字,必须通过传递进来的参数对象加点号来访问(例如 rhs.val)。
补充笔记:运算符的重载方式选择 (Member vs Friend)
在 C++ 中,运算符重载的选择并非随意,编译器对不同运算符有严格的规定。以下为四大类核心场景:
1. 必须且只能用“成员函数 (Member Function)”重载
这类运算符与对象的内存状态或生命周期高度绑定,左操作数必须是该类的对象。
包含: 赋值
=、下标[]、函数调用()、成员访问->记忆口诀: “等号、中括号、小括号、箭头” 这四个是类的“私有财产”,绝不允许非成员函数插手。
2. 通常必须用“友元函数 / 非成员函数 (Friend Function)”重载
这类运算符的左操作数通常不是自定义类,而是标准库类(如 ostream 或 istream)。
包含: 流插入
<<、流提取>>核心逻辑: 为了保持
cout << obj;这种符合直觉的写法,左操作数必须是ostream对象,因此只能写成全局非成员函数:operator<<(ostream& out, const MyClass& obj)。通常将其声明为 friend 以便访问类内的私有成员。
3. 两者皆可(Member 或 Friend 都可以)
绝大多数常规的二元运算符都属于这一类。
包含: 算术 (
+,-,*), 关系 (==,<), 复合赋值 (+=), 自增自减 (++,--) 等。最佳实践经验:
改变对象自身状态的(如
+=,++):强烈建议用 Member function。不改变双方状态且具对称性的(如
+,==):强烈建议用 Friend function。因为友元函数允许左右两边的操作数都进行隐式类型转换(例如obj + 5和5 + obj均可顺利编译)。
4. 绝对不能被重载的运算符
为了保证 C++ 基础语法的解析不崩溃,以下 5 个运算符绝对禁止重载:
- 成员访问
.、成员指针访问.*、作用域解析::、三目条件?:、获取大小sizeof。
终极总结速查表
| 运算符类别 | 示例 | 必须 Member? | 必须 Friend? | 两者皆可? |
|---|---|---|---|---|
| 类的核心行为 | =, [], (), -> |
\(✓\) 是 | \(\times\) 否 | \(\times\) 否 |
| 标准 IO 流操作 | <<, >> (配合 cin/cout) |
\(\times\) 否 | \(✓\) 是 | \(\times\) 否 |
| 修改对象自身状态 | +=, -=, ++, -- |
\(\times\) 否 | \(\times\) 否 | \(✓\) 可以 (推荐 Member) |
| 对称计算与比较 | +, -, ==, < |
\(\times\) 否 | \(\times\) 否 | \(✓\) 可以 (推荐 Friend) |
| 底层语法解析 | ., ::, ?:, sizeof |
- | - | 严禁重载 |
Operator Overloading & Polymorphism Concepts
Concept 1: Assignment Operator
赋值运算符可以重载,但是无论参数为何种类型,赋值运算符都必须重载为成员函数,并且因为返回的是左值,所以返回值的类型必须是该类的 。
答案: 引用(或 类名&)
解析: 赋值运算符 = 为了支持连续赋值操作(如 a = b = c;),其返回值必须是可以被修改的左值。因此,它必须返回调用该运算符的对象自身的引用(即 return *this;),其标准函数签名通常为 ClassName& operator=(const ClassName& rhs);。
Concept 2: Parameter Counts & Polymorphism Definition
运算符重载为类的成员函数时,函数参数个数比原来的运算符个数 ,当重载为类的友元函数时,参数个数与原来运算符个数 。多态指不同对象接收 时产生的 。
答案: 少一个、相同、相同的消息、不同行为
解析:
参数个数: 重载为成员函数时,左操作数充当了隐藏的
this指针,所以显式参数少一个;重载为友元函数时无隐藏指针,所有操作数都要显式传入。多态本质: 面向对象中的多态,核心定义就是“不同的对象接收到相同的消息(即调用同名接口),由于内部具体实现不同,从而表现出不同的响应行为”。
Concept 3: Overloading Methods
运算符重载函数的两种主要方式是 、。
答案: 成员函数、友元函数(或普通全局函数)
Concept 4: Types of Polymorphism (Execution)
从运行的角度多态可分为 和 。
答案: 静态多态(编译时多态)、动态多态(运行时多态)
解析: 静态多态主要依赖函数重载、运算符重载和模板(Template)在编译期决断;动态多态则主要依赖继承和虚函数(virtual)在运行期决断。
Concept 5: Function Overloading
函数重载就是一种 ,相同的函数名,对应多个不同的函数体。
答案: 静态多态(或编译时多态)
解析: 编译器在编译阶段,就能根据传入实参的“类型、数量、顺序”组成的函数签名,唯一确定需要绑定哪一个具体的函数版本,无需拖延到运行时。
Concept 6: Overloading Polymorphism
函数重载和 都属于重载多态。
答案: 运算符重载
解析: 广义的多态可分为四大类:重载多态(函数/运算符重载)、强制多态(类型转换)、包含多态(虚函数)、参数多态(模板)。
Concept 7: Coercion Polymorphism
强制类型转换是通过 来实现的。
答案: 类型转换函数(如 operator int()) 或 强制多态
解析: 在 C++ 类的语境下,实现隐式或强制类型转换靠的是自定义的类型转换重载函数。
Concept 8: Binding Phases
按照联编所进行的阶段不同,可分为两种不同的联编方法: 和 。
答案: 静态联编(早期联编/编译时联编)、动态联编(晚期联编/运行时联编)
解析: 联编(Binding)即将函数调用语句与具体的函数体内存代码绑定在一起的过程。
Concept 9: Dynamic Binding Core
动态联编对函数的选择不是基于指针或者引用,而是基于 ,在编译、链接过程中无法解决的绑定问题要等到程序开始运行之后再确定。
答案: 指针或引用所指向对象的实际类型
解析: 这是动态多态的灵魂。例如 Base* ptr = new Derived();,ptr 的静态类型是基类指针,但它真正在内存中指向的实际类型是派生类。动态联编会通过查找虚函数表(vtable),在运行时精准调用派生类重写的虚函数。
Concept 10: Copy Constructor vs. Assignment Operator (拷贝构造与赋值重载的易错区分)
在 C++ 中,“=” 符号在不同的上下文中有两种完全不同的含义,这是考试和面试中最常见的陷阱。核心的判断标准只有一个:赋值号左边的对象是否已经存在?
1. 拷贝构造函数 (Copy Constructor): A(const A &)
核心动作:初始化 (Initialization)
触发条件: 正在创建一个全新的对象,并用一个同类型的、已存在的对象来初始化它。此时该对象在内存中刚刚被分配空间。
典型代码:
A d = a;(在 C++ 编译器眼中,这行代码与A d(a);完全等价,绝不会调用operator=)。其他隐式调用场景 (极易考):
将对象作为实参,按值传递给函数参数时(例如调用
void func(A obj);)。函数按值返回一个局部对象时(例如
A func() \{ return a; \})。
2. 赋值运算符重载 (Assignment Operator): A& operator=(const A &)
核心动作:赋值 (Assignment)
触发条件: 针对一个已经存在(在之前的代码中早就已经被构造函数创建好)的对象,修改或覆盖它的状态。
典型代码:
c = a;(前提是c在这行代码之前就已经通过诸如A c;声明过了)。
【一句话防坑口诀】:
**带有类型名声明的“`=`”**(例如 `A d = a;`)是在生孩子,**必定调用拷贝构造**;
**没有类型名、单独使用的“`=`”**(例如 `c = a;`)是在换衣服,**必定调用赋值重载**。
HW5
总览
本份笔记整理以下错题:1,2,7,10,16,19,22,26–27,28,32,35,37,38,39,44,45,47,50,51,54,55,57,58,62,以及一道虚函数输出分析题。
核心主线:
virtual function:普通虚函数,不一定要被派生类重写。
pure virtual function / abstract method:纯虚函数,若派生类要成为具体类,则必须实现。
abstract class:含有至少一个纯虚函数的类,不能直接创建对象,但可以创建指针或引用。
runtime polymorphism:必须通过基类指针或引用调用虚函数,才体现运行时多态。
以下说法正确的是?
A. 派生类可以和基类有同名成员函数,但是不能有同名成员变量
B. 派生类的成员函数中,可以调用基类的同名同参数表的成员函数
C. 派生类和基类的同名成员函数必须参数表不同,否则就是重复定义
D. 派生类和基类的同名成员变量存放在相同存储空间
查看答案与解析
答案:B
解析:正确选项是 B。派生类中可以定义和基类同名、同参数表的成员函数,这不是重复定义,而是隐藏或重定义。如果要在派生类成员函数中调用基类版本,可以使用作用域限定符:
class Base {
public:
void show() {}
};
class Derived : public Base {
public:
void show() {
Base::show(); // 调用基类同名同参数函数
}
};
**易错点:**派生类也可以和基类有同名成员变量,但它们是两个不同的成员,存放在不同的空间。
Which among the following can show polymorphism?
A. Overloading
&&B. Overloading
<<C. Overloading
||D. Overloading
+=
查看答案与解析
答案:B
**解析:**题库预期答案是 B。在很多 OOP 题库中,<< 被当作最典型的运算符重载例子,例如:
cout << 1;
cout << 3.14;
cout << "hello";
cout << user_defined_object;
同一个运算符面对不同类型产生不同效果,因此体现了重载多态/编译期多态。
**注意:**严格 C++ 语法上,+= 也可以重载,例如自定义向量类的 operator+=。所以本题不是问“哪个能不能被重载”,而是按题库习惯选择最典型的 <<。
**If a virtual member function is defined **
A. It should not contain any body and defined by subclasses
B. It must contain body and overridden by subclasses
C. It must contain body and be overloaded
D. It must not contain any body and should not be derived
查看答案与解析
答案:B
**解析:**题库语境下选 B,但这里的英文表述不严谨。普通虚函数通常可以有函数体:
class Base {
public:
virtual void f() {
cout << "Base f" << endl;
}
};
派生类可以重写它,但不是必须重写。如果题目说的是 pure virtual function,才是没有函数体、需要派生类实现:
class Base {
public:
virtual void f() = 0; // pure virtual function
};
**一句话:**普通 virtual 可以有函数体;纯虚函数写成 =0。
What does a virtual function ensure for an object, among the following?
A. Correct method is called, regardless of the class defining it
B. Correct method is called, regardless of the object being called
C. Correct method is called, regardless of the type of reference used for function call
D. Correct method is called, regardless of the type of function being called by objects
查看答案与解析
答案:C
解析:正确选项是 C。虚函数保证:即使使用基类指针或引用调用函数,也会根据对象的实际类型调用正确版本。
class Base {
public:
virtual void f() { cout << "Base" << endl; }
};
class Derived : public Base {
public:
void f() override { cout << "Derived" << endl; }
};
Base* p = new Derived;
p->f(); // 输出 Derived
**核心:**看的是对象实际类型,而不是指针/引用表面上的类型。
Which is a must condition for virtual function to achieve runtime polymorphism?
A. Virtual function must be accessed with direct name
B. Virtual functions must be accessed using base class object
C. Virtual function must be accessed using pointer or reference
D. Virtual function must be accessed using derived class object only
查看答案与解析
答案:C
解析:正确选项是 C。运行时多态必须通过基类指针或基类引用调用虚函数。若直接使用对象调用,通常在编译期已经确定类型,不体现动态绑定。
Base* p = new Derived;
p->f(); // runtime polymorphism
Base& r = derived_object;
r.f(); // runtime polymorphism
It is to redefine the virtual function in derived class.
A. Necessary
B. Not necessary
C. Not acceptable
D. Good practice
查看答案与解析
答案:B
**解析:**正确选项应为 B。普通虚函数不一定要在派生类中重写。如果派生类没有重写,就继承并使用基类版本。
class Base {
public:
virtual void f() {
cout << "Base f" << endl;
}
};
class Derived : public Base {
// 不重写 f(),仍然可以实例化
};
Derived d;
d.f(); // 调用 Base::f()
**易错点:**如果是纯虚函数 virtual void f() = 0;,派生类要成为具体类才必须实现。普通 virtual 不必须重写。
Which among the following is true?
A. The abstract functions must be only declared in derived classes
B. The abstract functions must not be defined in derived classes
C. The abstract functions must be defined in base and derived class
D. The abstract functions must be defined either in base or derived class
查看答案与解析
答案:D
**解析:**题库一般选 D,但选项表述不够严谨。C++ 中抽象函数通常指纯虚函数:
virtual void f() = 0;
它在基类中通常只声明,不给普通函数体;若派生类要成为具体类,则必须在派生类中实现。
**更准确的 C++ 说法:**抽象函数在基类中声明为纯虚函数;具体派生类必须实现它。
Given:
class A {
A() {};
virtual f() {};
int i;
};
which statement is NOT true?
A.
iis privateB.
f()is an inline functionC.
iis a member of class AD.
sizeof(A) == sizeof(int)
查看答案与解析
答案:D
**解析:**不正确的是 D。因为类中含有虚函数,通常对象内部会额外包含一个虚函数表指针(vptr)。因此对象大小通常不只是一个 int 的大小。
纯虚函数版本:
class A {
A() {}
virtual f() = 0;
int i;
};
即使 f() 是纯虚函数,该类对象布局中通常也仍然需要 vptr。因此 sizeof(A) == sizeof(int) 仍然不成立。
**注意:**实际大小和编译器、平台、对齐规则有关,但通常会大于 sizeof(int)。
Given:
class X {
int i;
virtual void f() {};
};
If sizeof(int*) == sizeof(int) == 4, then sizeof(X)==?
A. 4
B. 6
C. 8
D. Undetermined
查看答案与解析
答案:C
**解析:**题库答案是 C。因为:
[
\texttt{int i} = 4\text{ bytes}, \quad \texttt{vptr} = 4\text{ bytes}
]
所以:
[
\texttt{sizeof(X)} = 4 + 4 = 8
]
**注意:**这是在题目已经明确 sizeof(int*) == sizeof(int) == 4 的前提下。
Which among the following is wrong?
A.
class student\{ \}; student s;B.
abstract class student\{ \}; student s;C.
abstract class student\{ \}s[50000000];D.
abstract class student\{ \}; class toppers: public student\{ \}; topper t;
查看答案与解析
答案:B
**解析:**题库通常考察点是:抽象类不能实例化。所以 student s; 若 student 是抽象类,就错误。
**注意:**这些选项不是标准 C++ 语法,因为 C++ 没有 abstract class 这种关键字写法。C++ 中抽象类通过纯虚函数形成:
class Student {
public:
virtual void f() = 0;
};
Student s; // 错,抽象类不能实例化
Which among the following best describes abstract classes?
A. If a class has more than one virtual function, it’s abstract class
B. If a class have only one pure virtual function, it’s abstract class
C. If a class has at least one pure virtual function, it’s abstract class
D. If a class has all the pure virtual functions only, then it’s abstract class
查看答案与解析
答案:C
**解析:**正确选项是 C。C++ 中只要一个类中有至少一个纯虚函数,它就是抽象类。
class A {
public:
virtual void f() = 0; // 至少一个纯虚函数
};
**If there is an abstract method in a class then, **
A. Class must be abstract class
B. Class may or may not be abstract class
C. Class is generic
D. Class must be public
查看答案与解析
答案:A
**解析:**正确选项是 A。如果一个类含有抽象方法,即纯虚函数,那么这个类就是抽象类。
class A {
public:
virtual void f() = 0;
}; // A 是抽象类
**If a class is extending/inheriting another abstract class having abstract method, then **
A. Either implementation of method or making class abstract is mandatory
B. Implementation of the method in derived class is mandatory
C. Making the derived class also abstract is mandatory
D. It’s not mandatory to implement the abstract method of parent class
查看答案与解析
答案:A
**解析:**正确选项是 A。派生类继承抽象类后有两种选择:
实现所有纯虚函数,成为具体类;
不完全实现,继续作为抽象类。
class A {
public:
virtual void f() = 0;
};
class B : public A {
// 不实现 f(),所以 B 仍然是抽象类
};
class C : public A {
public:
void f() override {} // C 实现了 f(),C 可以实例化
};
Abstract class A has 4 virtual functions. Abstract class B defines only 2 of those member functions as it extends class A. Class C extends class B and implements the other two member functions of class A. Choose the correct option below.
A. Program won’t run as all the methods are not defined by B
B. Program won’t run as C is not inheriting A directly
C. Program won’t run as multiple inheritance is used
D. Program runs correctly
查看答案与解析
答案:D
**解析:**正确选项是 D。纯虚函数可以分层实现,不要求第一层派生类一次性全部实现。只要最终要实例化的类实现了全部纯虚函数,就可以创建对象。
class A {
public:
virtual void f1() = 0;
virtual void f2() = 0;
virtual void f3() = 0;
virtual void f4() = 0;
};
class B : public A {
public:
void f1() override {}
void f2() override {}
// f3 和 f4 没有实现,所以 B 仍然是抽象类
};
class C : public B {
public:
void f3() override {}
void f4() override {}
// f1、f2 来自 B;f3、f4 由 C 实现
};
int main() {
// A a; // 错
// B b; // 错
C c; // 对
}
**The abstract classes in Java can **
A. Implement constructors
B. Can’t implement constructor
C. Can implement only unimplemented methods
D. Can’t implement any type of constructor
查看答案与解析
答案:A
**解析:**正确选项是 A。Java 抽象类不能直接实例化,但它仍然可以有构造器。构造器会在创建派生类对象时被调用,用来初始化抽象父类部分。
**C++ 类比:**C++ 抽象类也可以有构造函数:
class Base {
public:
Base() { cout << "Base constructor" << endl; }
virtual void f() = 0;
};
It is to have an abstract method.
A. Not mandatory for an static class
B. Not mandatory for a derived class
C. Not mandatory for an abstract class
D. Not mandatory for parent class
查看答案与解析
答案:C
**解析:**题库语境偏 Java,正确选项是 C。Java 中抽象类不一定必须包含抽象方法。例如一个类可以被声明为 abstract,但里面没有 abstract method。
**C++ 注意:**C++ 中没有 abstract 关键字;一个类成为抽象类的条件就是至少有一个纯虚函数。因此在 C++ 语境下,“抽象类是否必须有抽象方法”应理解为:是的,至少有一个纯虚函数。
If single level inheritance is used and an abstract class is created with some undefined functions, can its derived class also skip some definitions?
A. Yes, always possible
B. Yes, possible if only one undefined function
C. No, at least 2 undefined functions must be there
D. No, the derived class must implement those methods
查看答案与解析
答案:A
**解析:**正确选项是 A。派生类可以继续不实现部分纯虚函数,但代价是它自己仍然是抽象类,不能实例化。
class A {
public:
virtual void f() = 0;
};
class B : public A {
// 可以不实现 f()
// 但 B 仍然是抽象类
};
Is it compulsory to have constructor for all the classes involved in multiple inheritance?
A. Yes, always
B. Yes, only if no abstract class is involved
C. No, only classes being used should have a constructor
D. No, they must not contain constructors
查看答案与解析
答案:C
**解析:**题库答案通常是 C。这题的关键是:不要求所有类都手动写构造函数。如果没有显式写构造函数,编译器会尝试生成默认构造函数。
class A {};
class B {};
class C : public A, public B {};
int main() {
C c; // 可以,编译器自动生成默认构造函数
}
**易错点:**默认构造函数当然也算构造函数。更准确说法是:创建对象时,所有基类子对象和成员对象都必须能够被成功构造,但不一定要程序员显式写构造函数。
Which among the following best defines the abstract methods?
A. Functions declared and defined in base class
B. Functions only declared in base class
C. Function which may or may not be defined in base class
D. Function which must be declared in derived class
查看答案与解析
答案:B
**解析:**题库答案是 B。抽象方法通常指在基类中只声明、没有普通实现的函数。在 C++ 中对应纯虚函数:
class Base {
public:
virtual void f() = 0;
};
**注意:**C++ 允许纯虚函数有类外定义,但这属于高级细节;考试题一般按“只声明不实现”来理解。
It is to define the abstract functions.
A. Mandatory for all the classes in program
B. Necessary for all the base classes
C. Necessary for all the derived classes
D. Not mandatory for all the derived classes
查看答案与解析
答案:D
**解析:**正确选项是 D。不是所有派生类都必须实现抽象函数,因为中间派生类可以继续保持抽象。
class A {
public:
virtual void f() = 0;
};
class B : public A {
// 不实现 f(),B 仍为抽象类
};
class C : public B {
public:
void f() override {} // C 成为具体类
};
**The abstract function definitions in derived classes is enforced at **
A. Runtime
B. Compile time
C. Writing code time
D. Interpreting time
查看答案与解析
答案:B
**解析:**正确选项是 B。如果一个类还没有实现所有纯虚函数,却尝试创建对象,编译器会直接报错。因此这是编译期检查。
class A {
public:
virtual void f() = 0;
};
class B : public A {};
int main() {
B b; // 编译期报错:B 仍然是抽象类
}
**If a function declared as abstract in base class doesn’t have to be defined in derived class then **
A. Derived class must define the function anyhow
B. Derived class should be made abstract class
C. Derived class should not derive from that base class
D. Derived class should not use that function
查看答案与解析
答案:B
**解析:**正确选项是 B。如果派生类不想实现基类中的抽象函数,那么这个派生类自身也必须保持抽象,不能创建对象。
Which among the following is true?
A. Abstract methods can be static
B. Abstract methods can be defined in derived class
C. Abstract methods must not be static
D. Abstract methods can be made static in derived class
查看答案与解析
答案:C
**解析:**正确选项是 C。抽象方法依赖虚函数机制,而 static 成员函数不属于某个对象,没有 this 指针,不能参与虚函数动态绑定。
class Base {
public:
static virtual void f() = 0; // 错
};
一句话:virtual 靠对象动态绑定;static 不依赖对象,所以二者不能同时用。
The abstract method definition can be made in derived class.
A. Private
B. Protected
C. Public
D. Private, public, or protected
查看答案与解析
答案:D
**解析:**正确选项是 D。C++ 中判断是否重写,主要看函数名、参数表、const 修饰、返回类型是否兼容,不看访问权限。因此基类中的 public 纯虚函数,可以在派生类中被 private/protected/public 方式重写。
class Base {
public:
virtual void f() = 0;
};
class Derived : public Base {
private:
void f() override {
cout << "Derived f" << endl;
}
};
**注意:**访问权限只影响能不能直接调用,不影响是否构成 override。
Derived d;
// d.f(); // 错,因为 Derived::f 是 private
Base* p = &d;
p->f(); // 可以,因为 Base::f 是 public,运行时绑定到 Derived::f
补充题:虚函数、const 与隐藏
题目代码:
#include<iostream>
using namespace std;
class Base{
protected:
int x;
public:
Base(int b=0): x(b) { }
virtual void display() const {cout << x << endl;}
};
class Derived: public Base{
int y;
public:
Derived(int d=0): y(d) { }
void display() {cout << x << "," << y << endl;}
};
int main()
{
Base b(1);
Derived d(2);
Base *p = &d;
b.display();
d.display();
p->display();
return 0;
}
输出:
1
0,2
0
解析 1:Base b(1)
Base b(1);
调用 Base(int b=0): x(b),所以 b.x = 1。因此:
b.display();
调用 Base::display() const,输出:
1
解析 2:Derived d(2)
Derived(int d=0): y(d) { }
这里只初始化了 y,没有显式调用基类构造函数,所以基类部分自动调用:
Base()
也就是 x = 0。同时 y = 2。因此:
d.display();
调用 Derived::display(),输出:
0,2
解析 3:为什么 p->display() 输出 0?
基类函数是:
virtual void display() const
派生类函数是:
void display()
注意:基类版本有 const,派生类版本没有 const。因此它们的函数签名不同,Derived::display() 并没有真正 override Base::display() const,而只是隐藏了基类同名函数。
所以:
Base *p = &d;
p->display();
调用的仍然是 Base::display() const。由于 d 的基类部分 x = 0,所以输出:
0
正确重写写法
如果想让它真正发生多态,应写成:
class Derived: public Base{
int y;
public:
Derived(int d=0): Base(d), y(d) { }
void display() const override {
cout << x << "," << y << endl;
}
};
这样:
const保持一致;使用
override让编译器检查是否真正重写;Base(d)让基类部分的x也初始化为d。
此时输出会变为:
1
2,2
2,2
HW6
总览
本份笔记按照前面整理出的 1–100 题编号记录,不重新编号。整理范围包括:
[
1,\ 5,\ 17,\ 18,\ 25,\ 27,\ 30,\ 31,\ 32,\ 34,\ 41,\ 43,\ 44,\ 49,\ 53,\ 55,\ 66,\ 67,\ 71\text{–}72,\ 87
]
以及前面单独问过的异常题:
[
69,\ 73,\ 78,\ 86,\ 93,\ 94.
]
核心主线:
template:模板不是具体代码,实例化后才形成具体函数或具体类。
class template:使用类模板创建对象时,一般需要写模板实参,如
MyClass<int> a(10);。STL:容器、迭代器、算法相互配合,不是完全孤立的三部分。
string:注意
cin >> s、getline、下标越界和字符运算。exception:多个
catch从上到下匹配;派生类异常应写在基类异常之前;throw;表示重抛当前异常。
一、模板与类模板
**原题:**现有声明:
template <class T>
class Test { ... };
则以下哪一个声明不可能正确?
A.
Test a;B.
Test<int> a;C.
Test<float> a;D.
Test<Test<int>> a;
查看答案与解析
[
\boxed{\text{答案:A}}
]
**解析:**类模板不是具体类,使用时通常要给出模板实参:
Test<int> a;
Test<float> b;
Test<Test<int>> c;
而
Test a;
没有说明 T 是什么类型,因此不正确。
**易错点:**函数模板可以通过函数实参自动推导类型,但类模板创建对象时,传统 C++ 语境下一般不能直接省略模板实参。本题按基础 C++ 题库语境处理。
**原题:**关于函数模板,描述错误的是。
A. 函数模板必须由程序员实例化为可执行的函数模板
B. 函数模板的实例化由编译器实现
C. 一个类定义中,只要有一个函数模板,则这个类是类模板
D. 类模板的成员函数都是函数模板,类模板实例化后,成员函数也随之实例化
查看答案与解析
[
\boxed{\text{严格看:A、C 都有问题;若单选,题库多半想考 A}}
]
解析:
A. “函数模板必须由程序员实例化”错误。函数模板通常由编译器根据调用自动实例化。
B. “函数模板的实例化由编译器实现”正确。
C. “一个类定义中只要有一个函数模板,则这个类是类模板”错误。普通类中也可以有成员函数模板。
D. “类模板的成员函数都是模板函数”是教材中的粗略说法,严格术语下不完全准确。
例如:
template<class T>
T myMax(T x, T y) {
return x > y ? x : y;
}
int main() {
myMax(1, 2); // 编译器自动实例化 myMax<int>
myMax(1.0, 2.0); // 编译器自动实例化 myMax<double>
}
补充:普通类也可以有成员函数模板。
class A {
public:
template<class T>
void print(T x) {
cout << x << endl;
}
};
这个 A 不是类模板。
**原题:**类模板的使用实际上是将类模板实例化成一个。
A. 函数
B. 对象
C. 类
D. 抽象类
查看答案与解析
[
\boxed{\text{答案:C}}
]
**解析:**类模板本身不是一个具体类。使用时,编译器把类模板实例化成具体类:
template<class T>
class Box {
T value;
};
Box<int> a; // Box<int> 是具体类
Box<double> b; // Box<double> 是另一个具体类
**一句话:**类模板 \(\to\) 模板类/具体类 \(\to\) 对象。
**原题:**下列关于模板的说法中,错误的是。
A. 用模板定义一个对象时,不能省略参数
B. 类模板只能有虚拟参数类型
C. 类模板的成员函数都是模板函数
D. 类模板在编译中不会生成任何代码
查看答案与解析
[
\boxed{\text{答案:B}}
]
**解析:**这里的“虚拟参数类型”是老教材说法,大致指 类型模板参数,例如:
template<class T>
class A {};
其中 T 是类型模板参数。
但类模板不只能有类型参数,还可以有 非类型模板参数:
template<class T, int N>
class Array {
T data[N];
};
Array<int, 10> a; // T = int, N = 10
关于“类模板的成员函数都是模板函数”:
template<class T>
class A {
public:
void test() {
cout << "hello";
}
};
这里 test() 没有自己的 template<class U>,所以严格说它不是“函数模板”,而是类模板的普通成员函数。但它会随着 A<int>、A<double> 等类模板实例化而生成对应版本。所以教材有时粗略地说“类模板的成员函数都是模板函数”。
**更准确的说法:**类模板的成员函数会随类模板实例化而实例化;只有自己带 template<class U> 的成员函数才严格叫成员函数模板。
**原题:**下列关于类模板的定义,正确的是。
A.
template<class T, int i = 0>B.
template<class T, class int i>C.
template<class T, typename T>D.
template<class T1, T2>
查看答案与解析
[
\boxed{\text{答案:A}}
]
解析:
template<class T, int i = 0>
class A {};
是合法的。这里 T 是类型模板参数,i 是非类型模板参数,并且 i 有默认值。
为什么 template<class T, typename T> 错?
template<class T, typename T>
class A {};
两个模板参数都叫 T,在同一作用域内重名,非法。类似于不能写:
void f(int x, double x) {}
正确写法应为:
template<class T, typename U>
class PairLike {};
**原题:**模板的使用是为了()。
A. 提高代码的可重用性
B. 提高代码的运行效率
C. 加强类的封装性
D. 实现多态性
查看答案与解析
[
\boxed{\text{答案:A}}
]
**解析:**模板让同一套代码适用于不同类型:
template<class T>
T add(T a, T b) {
return a + b;
}
这样既可以处理 int,也可以处理 double,主要目的就是代码复用。
**原题:**关于函数模板,描述错误的是( )。
A. 函数模板的实例化由编译器实现
B. 函数模板必须由程序员实例化为可执行的函数模板
C. 类模板的成员函数都是函数模板,类模板实例化后,成员函数也随之实例化
D. 一个类定义中,只要有一个函数模板,这个类就是类模板
查看答案与解析
[
\boxed{\text{严格看:B、D 都有问题;若单选,题库通常想考 B}}
]
解析:
A. 函数模板的实例化由编译器实现。正确。
B. 函数模板必须由程序员实例化。错误。通常编译器会根据调用自动实例化。
C. 类模板的成员函数随类模板实例化而实例化。教材语境中通常认为正确。
D. 一个类定义中只要有一个函数模板,这个类就是类模板。严格错误。
不用程序员自己实例化的例子:
template<class T>
T maxValue(T x, T y) {
return x > y ? x : y;
}
int main() {
int a = maxValue(3, 5); // 自动生成 maxValue<int>
double b = maxValue(3.1, 5.2); // 自动生成 maxValue<double>
}
程序员没有写:
maxValue<int>(3, 5);
maxValue<double>(3.1, 5.2);
但编译器会自动推导并实例化。
**原题:**A template class can have .
A. More than one generic data type
B. Only one generic data type
C. At most two data types
D. Only generic type of integers and not characters
查看答案与解析
[
\boxed{\text{答案:A}}
]
**解析:**类模板可以有多个类型参数:
template<class T1, class T2>
class MyPair {
T1 first;
T2 second;
};
使用时:
MyPair<int, double> p;
**原题:**Which is the most significant feature that arises by using template classes?
A. Code readability
B. Ease in coding
C. Code reusability
D. Modularity in code
查看答案与解析
[
\boxed{\text{答案:C}}
]
**解析:**类模板的核心价值是用一份类定义适配多种类型:
vector<int> vi;
vector<double> vd;
vector<string> vs;
vector 只写一套模板,但可以实例化出多种具体容器类型。
**原题:**How is function overloading different from template class?
A. Overloading is multiple function doing same operation, Template is multiple function doing different operations
B. Overloading is single function doing different operations, Template is multiple function doing different operations
C. Overloading is multiple function doing similar operation, Template is multiple function doing identical operations
D. Overloading is multiple function doing same operation, Template is same function doing different operations
查看答案与解析
[
\boxed{\text{答案:C}}
]
**解析:**函数重载是多个函数使用同一个函数名,但参数表不同;模板则是用同一个模式处理不同类型。题库选项中 C 最接近:
[
\text{Overloading:多个函数做相似操作;Template:同一模式处理不同类型。}
]
例如重载:
int maxValue(int a, int b);
double maxValue(double a, double b);
模板:
template<class T>
T maxValue(T a, T b);
**易错点:**重载强调“多个函数”;模板强调“一套代码模式,多种实例化”。
二、STL、迭代器与 pair
迭代器知识总括
STL 的核心结构:
容器 container:存数据,例如
vector,list,map,set。迭代器 iterator:像指针一样访问容器中的元素。
算法 algorithm:通过迭代器操作容器,例如
sort,find,copy。
常见迭代器类型:
Input Iterator:只能读,只能向前走。
Output Iterator:只能写,只能向前走。
Forward Iterator:可多次遍历,只能向前。
Bidirectional Iterator:可前进也可后退,如
list迭代器。Random Access Iterator:可随机访问,如
vector迭代器。
不存在“删除迭代器”这种基本迭代器类别。
**原题:**设有如下代码段:
std::map<char *, int> m;
const int MAX_SIZE = 100;
int main() {
char str[MAX_SIZE];
for (int i = 0; i < 10; i++) {
std::cin >> str;
m[str] = i;
}
std::cout << m.size() << std::endl;
}
读入 10 个字符串,则输出的 m.size() 为:
A. 0
B. 1
C. 10
查看答案与解析
[
\boxed{\text{答案:B}}
]
解析:map<char*, int> 的 key 是 char* 指针。这里每次输入都写入同一个数组 str,所以 str 转成指针后地址始终相同。于是 map 认为 key 一直是同一个,最终只有一个元素。
如果想按字符串内容作为 key,应使用:
std::map<std::string, int> m;
**原题:**下列关于 pair<> 类模板的描述中,错误的是。
A.
pair<>类模板定义在头文件utility中B.
pair<>类模板作用是将两个数据组成一个数据,两个数据可以是同一个类型也可以是不同的类型C. 创建
pair<>对象只能调用其构造函数D.
pair<>类模板提供了两个成员函数first与second来访问这两个数据
查看答案与解析
[
\boxed{\text{题库多半选:C;但 D 的表述也不严谨}}
]
解析:
A.
pair定义在头文件<utility>中。正确。B.
pair可以把两个数据组合成一个数据,二者类型可以相同也可以不同。正确。C. 创建
pair对象只能调用构造函数。错误,因为还可以用make_pair。D.
first和second不是成员函数,而是数据成员;所以这句话表述也不严谨。
示例:
#include <utility>
using namespace std;
pair<int, string> p1(1, "Tom");
auto p2 = make_pair(2, string("Jerry"));
cout << p1.first << " " << p1.second << endl;
严格记法:
p.first; // 数据成员
p.second; // 数据成员
不是:
p.first(); // 错
p.second(); // 错
**原题:**下列选项中,哪一项不是迭代器。
A. 输入迭代器
B. 前向迭代器
C. 双向迭代器
D. 删除迭代器
查看答案与解析
[
\boxed{\text{答案:D}}
]
**解析:**输入迭代器、前向迭代器、双向迭代器都是常见迭代器类别;没有“删除迭代器”这一基本类别。
注意:erase 是容器的删除操作,不是迭代器类别:
vector<int> v = {1, 2, 3};
auto it = v.begin();
v.erase(it);
三、string 与输入输出
**原题:**有代码如下:
string s;
s[0] = '1';
则关于以上语句说法正确的是( )。
A. 语句
"s[0]='1';"有问题B.
s的值为字符串"1"C.
s是空格串D.
s是空串
查看答案与解析
[
\boxed{\text{答案:A}}
]
**解析:**默认构造出的 s 是空字符串,没有第 0 个字符。直接访问 s[0] 越界,属于未定义行为。
正确做法:
string s;
s.push_back('1'); // 方法一
string t;
t.resize(1);
t[0] = '1'; // 方法二
**原题:**有代码如下:
int n;
string s;
cin >> n;
getline(cin, s);
cout << s.size() << endl;
则在输入以下数据后得到结果是( )。
1
Hello World
A. 11
B. 0
C. 5
D. 12
查看答案与解析
[
\boxed{\text{答案:B}}
]
解析:cin >> n 只读走数字 1,但留下后面的换行符 '\ n'。紧接着 getline(cin, s) 会读到这个换行符之前的空内容,所以 s 是空串,长度为 0。
正确写法:
int n;
string s;
cin >> n;
cin.ignore(); // 丢掉换行符
getline(cin, s);
如果担心缓冲区中还有更多字符,可以写:
cin.ignore(numeric_limits<streamsize>::max(), '\n');
**原题:**以下代码的输出结果是( )。
string res="";
string s,t="123456";
s=string(3,'0'); //相当于s="000";
s=s+"123";
for(int i=5;i>=0;i--) {
char c=s[i]+t[i]-'0';
res=c+res;
}
cout<<res<<endl;
A. 975321
B. 236456
C. 654632
D. 123579
查看答案与解析
[
\boxed{\text{答案:D}}
]
**解析:**这里不是整数加法,而是字符运算。逐位计算:
[
\begin{aligned}
0+1 &\to 1,\
0+2 &\to 2,\
0+3 &\to 3,\
1+4 &\to 5,\
2+5 &\to 7,\
3+6 &\to 9.
\end{aligned}
]
因此结果是:
123579
**易错点:**代码没有处理进位,所以不是普通的大整数加法模板,只是每一位单独相加。
四、异常处理
**原题:**What is wrong in the following code?
vector<int> v;
v[0] = 2.5;
A. The program has a compile error because there are no elements in the vector.
B. The program has a compile error because you cannot assign a double value to
v[0].C. The program has a runtime error because there are no elements in the vector.
D. The program has a runtime error because you cannot assign a double value to
v[0].
查看答案与解析
[
\boxed{\text{答案:C}}
]
解析:vector<int> v; 创建的是空容器,此时没有第 0 个元素。访问 v[0] 越界。
严格 C++ 说法:v[0] 越界是未定义行为,不一定稳定表现为“运行时错误”。但考试题一般按运行时错误处理。
注意:2.5 赋给 int 可以发生类型转换,不是主要错误。
正确做法:
vector<int> v;
v.push_back(2); // 先插入元素
v[0] = 2;
**原题:**If you enter 1 0, what is the output of the following code?
#include "iostream"
using namespace std;
int main()
{
cout << "Enter two integers: ";
int number1, number2;
cin >> number1 >> number2;
try
{
if (number2 == 0)
throw number1;
cout << number1 << " / " << number2 << " is "
<< (number1 / number2) << endl;
cout << "C" << endl;
}
catch (int e)
{
cout << "A";
}
cout << "B" << endl;
return 0;
}
A. A
B. B
C. C
D. AB
查看答案与解析
[
\boxed{\text{答案:D}}
]
**解析:**输入 number1 = 1, number2 = 0,所以抛出 int 类型异常。程序跳到:
catch (int e) {
cout << "A";
}
输出 A。然后 catch 结束后,继续执行:
cout << "B" << endl;
所以最终输出:
AB
**原题:**Which of the following statements are true?
A. A custom exception class is just like a regular class.
B. A custom exception class must always be derived from class exception.
C. A custom exception class must always be derived from a derived class of class exception.
D. A custom exception class must always be derived from class runtime_error.
查看答案与解析
[
\boxed{\text{答案:A}}
]
**解析:**C++ 中自定义异常类本质上就是普通类,不要求必须继承 std::exception:
class MyException {};
throw MyException();
工程上推荐:
class MyException : public std::exception {
public:
const char* what() const noexcept override {
return "MyException";
}
};
这样可以用:
catch (const std::exception& e) {
cout << e.what();
}
共同代码:
try {
statement1;
statement2;
statement3;
}
catch (Exception1 ex1)
{
}
catch (Exception2 ex2)
{
}
catch (Exception3 ex3)
{
statement4;
throw;
}
statement5;
**原题:**Suppose that statement2 throws an exception of type Exception2 in the above statement. Which statement is executed after statement2 is executed?
A. statement2
B. statement3
C. statement4
D. statement5
查看答案与解析
[
\boxed{\text{Question 71 答案:D}}
]
执行流程:
执行
statement1。执行
statement2,抛出Exception2。statement3不执行。进入
catch(Exception2 ex2)。该
catch中没有throw;,所以异常处理结束。继续执行
statement5。
**原题:**Suppose that statement3 throws an exception of type Exception3 in the above statement. Which statements are executed after statement3 is executed?
A. statement2
B. statement3
C. statement4
D. statement5
查看答案与解析
[
\boxed{\text{Question 72 答案:C}}
]
执行流程:
执行
statement1。执行
statement2。执行
statement3,抛出Exception3。进入
catch(Exception3 ex3)。执行
statement4。执行
throw;,重抛当前异常。当前
try-catch后面的statement5不执行。
核心区别:
[
\texttt{catch(Exception2)}\text{ 没有重抛,所以继续执行 statement5;}
]
[
\texttt{catch(Exception3)}\text{ 有 \texttt{throw;},所以异常继续向外传播。}
]
**原题:**下列关于异常处理的说法不正确的是( )。
A. 异常处理的
throw与catch通常不在同一个函数中,实现异常检测与异常处理的分离。B.
catch语句块必须跟在try语句块的后面,一个try语句块后可以有多个catch语句块。C. 在对函数进行异常规范声明时,若形参表后没有任何表示抛出异常类型的说明,它表示该函数不能抛出任何异常。
D.
catch语句块中,catch(...)表示该catch可以捕捉任意类型的异常,必须将catch(...)放在catch结构的最后。
查看答案与解析
[
\boxed{\text{答案:C}}
]
**解析:**普通函数声明:
void f();
并不表示 f 不能抛出异常。它只是没有写异常说明。
如果要表示函数不抛异常,C++11 以后应写:
void f() noexcept;
旧式写法是:
void f() throw();
**原题:**下列关于断言的描述中,错误的是。
A. 断言是调试程序的一种手段
B. 若断言情况发生,一般会终止程序
C. 在 C++ 中,宏
assert()用来在调试阶段实现断言D. 断言在程序调试与发布版本中都可以使用断言
查看答案与解析
[
\boxed{\text{答案:D}}
]
解析:assert() 主要用于调试阶段。若断言失败,一般会终止程序:
#include <cassert>
int x = -1;
assert(x > 0); // 断言失败,通常终止程序
如果发布版本中定义了 NDEBUG,断言通常会被关闭:
#define NDEBUG
#include <cassert>
**一句话:**断言是给程序员调试用的,不是给用户处理运行时错误用的。
**原题:**How many catch blocks can a single try block can have?
A. Only 1
B. Only 2
C. Maximum 127
D. As many as required
查看答案与解析
[
\boxed{\text{答案:D}}
]
**解析:**一个 try 后面可以跟多个 catch:
try {
// code
}
catch (const runtime_error& e) {
}
catch (const logic_error& e) {
}
catch (const exception& e) {
}
catch (...) {
}
多个 catch 从上往下匹配,只执行第一个匹配成功的。一般顺序:
[
\text{派生类异常} \to \text{基类异常} \to \texttt{catch(…)}
]
**原题:**To catch the exceptions .
A. An object must be created to catch the exception
B. A variable should be created to catch the exception
C. An array should be created to catch all the exceptions
D. A string have to be created to store the exception
查看答案与解析
[
\boxed{\text{考试答案:B}}
]
**解析:**题库想表达的是常见写法:
try {
throw 10;
}
catch (int e) {
cout << e;
}
这里 e 是 catch 参数变量。
**但严格 C++ 说法:**这个题目本身不严谨。因为 C++ 中可以不写变量名:
catch (const runtime_error&) {
cout << "caught";
}
也可以用:
catch (...) {
cout << "caught anything";
}
所以:
A. “必须创建对象来捕获异常”不准确,异常对象是在
throw时产生的。B. “应该创建一个变量”更符合题库语法意图,但不是严格必要条件。
**原题:**If catching of base class exception is done before derived class in C++ .
A. It gives compile time error
B. It doesn’t run the program
C. It may give warning but not error
D. It always gives compile time error
查看答案与解析
[
\boxed{\text{答案:C}}
]
**解析:**如果基类异常写在派生类异常前面:
try {
throw runtime_error("error");
}
catch (const exception& e) {
cout << "base";
}
catch (const runtime_error& e) {
cout << "derived";
}
由于 runtime_error 是 exception 的派生类,第一个 catch 已经能捕获它,后面的派生类 catch 就不可达。
通常不是编译错误,但编译器可能 warning。
正确顺序:
catch (const runtime_error& e) {
}
catch (const exception& e) {
}
**原题:**If a catch block accepts more than one exceptions then .
A. The catch parameters are not final
B. The catch parameters are final
C. The catch parameters are not defined
D. The catch parameters are not used
查看答案与解析
[
\boxed{\text{答案:B}}
]
**解析:**这题是 Java multi-catch 语法,不是 C++ 语法。例如 Java 中:
try {
// code
}
catch (IOException | SQLException e) {
// e is implicitly final
}
这里 e 是隐式 final,不能重新赋值。
**C++ 注意:**C++ 不支持这种写法:
catch (Exception1 | Exception2 e) { } // C++ 错误
C++ 通常写多个 catch,或者捕获共同基类。
五、最开始单独问过的题号映射
| 你最开始问的问题 | 对应题号 | 核心结论 |
|---|---|---|
自定义异常类是否必须继承 exception |
Question 69 | 不必须,答案 A |
try 后可以有几个 catch |
Question 86 | 按需多个,答案 D |
catch 中为什么还能 throw; |
Question 72 | throw; 是重抛当前异常 |
| 异常处理说法不正确 | Question 73 | void f(); 不代表不能抛异常,答案 C |
| 断言是什么 | Question 78 | assert 调试用,发布版可能关闭,答案 D |
| 基类异常先于派生类异常捕获 | Question 93 | 可能 warning,但通常非 error,答案 C |
| 一个 catch 捕获多个异常 | Question 94 | Java multi-catch,参数隐式 final,答案 B |
六、最后速记
类模板创建对象一般要写模板实参:
Test<int> a;。函数模板通常由编译器根据调用自动实例化,不需要程序员手动实例化。
类模板可以有类型参数,也可以有非类型参数,如
template<class T, int N>。pair的first和second是数据成员,不是成员函数。STL 不是容器、迭代器、算法三者互不相干;算法靠迭代器操作容器。
map<char*, int>比较的是指针地址,不是字符串内容。空
string不能直接写s[0]='1'。cin >> n后接getline,要先处理换行符。空
vector不能直接访问v[0]。多个
catch从上往下匹配;派生类异常放前,基类异常放后。throw;只能在处理异常时用于重抛当前异常。assert是调试手段,不应作为发布版错误处理机制。Java 的 multi-catch 和 C++ 的异常语法不要混在一起。
原始资料下载
| 作业 | TeX | |
|---|---|---|
| HW1 | criticalNotes.tex | criticalNotes.pdf |
| HW2 | pta2.tex | pta2.pdf |
| HW3 | pta3.tex | pta3.pdf |
| HW4 | pta4.tex | pta4.pdf |
| HW5 | pta5.tex | pta5.pdf |
| HW6 | pta6.tex | pta6.pdf |
总结:如何复习这组错题
- 先判断题目考查的是语言规则、对象模型,还是特定教材的术语。
- 代码题先做名字查找、重载决议和静态类型分析,再考虑运行期动态绑定。
- 涉及生命周期时,按“构造顺序与析构逆序”画出对象关系。
- 涉及多态时,检查虚函数签名、
const、访问权限和调用表达式的静态类型。 - 模板与 STL 题优先区分模板定义、实例化、容器、迭代器和算法各自的职责。
- 对题库中“必定”“只能”等绝对表述保持警惕,并结合当前 C++ 标准验证。
