Files
OOP-Cpp/oop_hw6/hw1/QA1.md
2025-08-11 00:01:30 +08:00

157 lines
4.2 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

### **1去掉(1)中的 `virtual`,比较执行结果。**
```cpp
virtual ~A() {...}
```
如果去掉 `virtual`,在通过 `A* p = new B;` 创建对象并用 `delete p;` 释放时:
* **原代码**:会先调用 `B::~B()`,再调用 `A::~A()`(因为析构函数是虚函数,发生动态绑定,析构顺序正确)。
* **去掉 `virtual` 后**:只会调用 `A::~A()`,不会调用 `B::~B()`**可能导致子类资源未释放,产生内存泄漏或行为异常**。
**结论**:基类应将析构函数设为 `virtual`,以确保通过基类指针删除时能调用子类析构函数。
---
### **2去掉(6)中的 `const`,可以吗?**
```cpp
virtual int Func1() const;
```
不可以。因为你在基类 A 中定义的是:
```cpp
virtual int Func1() const = 0;
```
这是一个**纯虚函数**,要求派生类重写时函数签名必须完全一致。如果你去掉 `const`,则签名不同,**不会重写该函数**,导致类 `B` 仍然是抽象类,不能实例化。
---
### **3(3) 和 (7) 中各自定义了参数的缺省值,(12) 执行时匹配的是哪个缺省值?为什么?**
```cpp
// A 类中:
virtual void Func2(int = 500) = 0;
// B 类中:
virtual void Func2(int = 1000)
```
语句 `(12)` 是:
```cpp
p->Func2(); // 没传参数
```
此时 `p``A*` 类型。**函数的缺省参数在编译时根据指针静态类型决定**,所以用的是 `A::Func2(int=500)` 中的默认值。
**结论**
* 缺省参数值是静态绑定的,跟对象的动态类型无关。
* 编译时看的是指针类型 `A*`,所以用了 `500` 而不是 `1000`
---
### **4(4) 中的 `protected` 改为 `private` 可以吗?**
```cpp
protected:
static int lineno;
```
如果改为 `private`**派生类 `B` 就不能访问 `lineno`,会导致编译错误**(如构造函数中 `++lineno`)。
**结论**:基类希望子类访问成员变量,应使用 `protected``private` 不可被子类访问。
---
### **5去掉 (5) 中的 `virtual`,对结果有影响吗?**
```cpp
virtual ~B() { ... }
```
如果 `~A()` 是虚函数,那么即使 `~B()` 不是虚函数,也会通过动态绑定调用 `~B()`
**结论**:去掉 `virtual` 不影响结果(只要基类析构函数是虚函数),但建议保留以提高可读性和一致性。
---
### **6(9) 的作用是什么?**
```cpp
int A::lineno = 0;
```
这是静态成员变量 `lineno` 的定义和初始化,**必须在类外初始化**,否则会链接错误。
**作用**:为类的所有对象共享一份 `lineno` 计数器,用来输出行号。
---
### **7(10) 中改为 `A* p = new A;` 可以吗?**
```cpp
A * p = new A; // 错误
```
`A` 是抽象类(包含纯虚函数),**不能实例化**。会导致编译错误。
**结论**:抽象类不能直接创建对象,只能用于指针或引用指向派生类。
---
### **8去掉(3)中的 `virtual`,结果会有什么改变?**
```cpp
void Func2(int = 500) = 0; // 去掉 virtual -> 变成普通纯函数?
```
这在语义上是错误的。**纯虚函数必须是虚函数**,否则语法不合法。
**结论**:不能去掉,纯虚函数必须是 `virtual`
---
### **9(14) 为什么不对?将 (8) 改为 `virtual` 后,(14) 可以了吗?**
```cpp
// (14) p->Func3(100);
```
`p``A*`,而 `Func3()` 并未在 `A` 中声明,因此不能通过 `A*` 调用,即使 `Func3()``virtual`
**结论**
* 静态类型决定能否调用某函数。
* 即使改成虚函数,也需要 `A` 中声明它,才能通过 `A*` 调用。
---
### **10(15) 为什么不对?理解编译时静态类型和运行时动态类型的含义。**
```cpp
// p->Func1(100); // 错误
```
`B` 中有两个重载版本:
```cpp
int Func1(int n) const;
int Func1() const;
```
`A* p` 只能看到 `A::Func1() const` 版本(无参数)。你尝试调用的是 `Func1(int)`,这在 `A` 中根本没有定义,编译时报错。
**结论**
* 编译时由静态类型决定调用哪个函数(是否存在该函数签名)。
* 运行时由动态类型决定调用哪个版本(多态行为)。
* 所以 `p->Func1(100)` 不合法,因为 `A` 中没这个函数签名。