OOP HomeWork

This commit is contained in:
e2hang
2025-08-11 00:01:30 +08:00
commit e8a5ca2363
119 changed files with 3187 additions and 0 deletions

156
oop_hw6/hw1/QA1.md Normal file
View File

@@ -0,0 +1,156 @@
### **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` 中没这个函数签名。