-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathvirtual_demo.cpp
More file actions
321 lines (260 loc) · 9.83 KB
/
Copy pathvirtual_demo.cpp
File metadata and controls
321 lines (260 loc) · 9.83 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
/**
* @file virtual_demo.cpp
* @brief 2.5 虚函数深度剖析 —— 完整示例代码
* @author 青松与桑叶
*
* 编译: g++ -std=c++17 -Wall -o virtual_demo virtual_demo.cpp
* 运行: ./virtual_demo
*
* 注意:本文件使用函数指针打印 vtable 地址,属于底层实现探索。
* 不同编译器和编译选项可能导致输出不同。
*/
#include <iostream>
#include <string>
#include <cstdint>
using namespace std;
// ============================================================
// 辅助函数:打印 vtable 信息
// ============================================================
// 虚函数指针类型
using VFunc = void(*)();
/**
* @brief 打印对象的 vtable 地址和虚函数指针
* @param obj 对象指针
* @param className 类名(用于显示)
* @param vfuncCount 虚函数数量
*/
void printVtable(void* obj, const string& className, int vfuncCount) {
// 读取对象前 8 字节(vptr)
uintptr_t vptr = *reinterpret_cast<uintptr_t*>(obj);
cout << " " << className << " 对象地址: " << obj << endl;
cout << " " << className << " vptr 地址: " << reinterpret_cast<void*>(vptr) << endl;
// 读取 vtable 中的函数指针
auto vtable = reinterpret_cast<uintptr_t*>(vptr);
for (int i = 0; i < vfuncCount; i++) {
cout << " vtable[" << i << "] = " << reinterpret_cast<void*>(vtable[i]) << endl;
}
cout << endl;
}
// ============================================================
// 第一部分:单继承下的 vtable 布局
// ============================================================
class Base1 {
public:
int baseData = 100;
virtual void func1() {
cout << " Base1::func1() 被调用" << endl;
}
virtual void func2() {
cout << " Base1::func2() 被调用" << endl;
}
virtual ~Base1() {
cout << " Base1 析构" << endl;
}
};
class Derived1 : public Base1 {
public:
int derivedData = 200;
// 重写 func1
void func1() override {
cout << " Derived1::func1() 被调用" << endl;
}
// 新增虚函数 func3
virtual void func3() {
cout << " Derived1::func3() 被调用" << endl;
}
~Derived1() override {
cout << " Derived1 析构" << endl;
}
};
void demo_single_inheritance_vtable() {
cout << "===== 单继承下的 vtable 布局 =====" << endl;
cout << "\n--- Base1 的 vtable ---" << endl;
Base1 b1;
// Base1 的 vtable 有 3 个条目:func1, func2, ~Base1
printVtable(&b1, "Base1", 3);
cout << "--- Derived1 的 vtable ---" << endl;
Derived1 d1;
// Derived1 的 vtable 有 4 个条目:func1(重写), func2(继承), ~Derived1, func3(新增)
printVtable(&d1, "Derived1", 4);
// 验证:通过基类指针调用虚函数
cout << "--- 通过基类指针调用虚函数 ---" << endl;
Base1* ptr = &d1;
ptr->func1(); // 应该调用 Derived1::func1()
ptr->func2(); // 应该调用 Base1::func2()
// 对象大小对比
cout << "\n--- 对象大小 ---" << endl;
cout << " sizeof(Base1): " << sizeof(Base1) << " 字节" << endl;
cout << " sizeof(Derived1): " << sizeof(Derived1) << " 字节" << endl;
cout << " (vptr 8 字节 + baseData 4 字节 + 对齐 + derivedData 4 字节)" << endl;
}
// ============================================================
// 第二部分:多重继承下的 vptr
// ============================================================
class BaseA {
public:
int dataA = 1;
virtual void funcA() {
cout << " BaseA::funcA() 被调用" << endl;
}
virtual ~BaseA() {
cout << " BaseA 析构" << endl;
}
};
class BaseB {
public:
int dataB = 2;
virtual void funcB() {
cout << " BaseB::funcB() 被调用" << endl;
}
virtual ~BaseB() {
cout << " BaseB 析构" << endl;
}
};
class MultiDerived : public BaseA, public BaseB {
public:
int dataC = 3;
void funcA() override {
cout << " MultiDerived::funcA() 被调用" << endl;
}
void funcB() override {
cout << " MultiDerived::funcB() 被调用" << endl;
}
~MultiDerived() override {
cout << " MultiDerived 析构" << endl;
}
};
void demo_multiple_inheritance_vptr() {
cout << "\n===== 多重继承下的 vptr =====" << endl;
MultiDerived md;
cout << "--- 对象大小 ---" << endl;
cout << " sizeof(MultiDerived): " << sizeof(MultiDerived) << " 字节" << endl;
cout << "\n--- BaseA 部分的 vtable ---" << endl;
BaseA* pA = &md;
cout << " pA (BaseA*) 地址: " << pA << endl;
printVtable(pA, "BaseA", 2); // funcA, ~BaseA
cout << "--- BaseB 部分的 vtable ---" << endl;
BaseB* pB = &md;
cout << " pB (BaseB*) 地址: " << pB << endl;
cout << " 地址偏移: " << (reinterpret_cast<char*>(pB) - reinterpret_cast<char*>(pA))
<< " 字节" << endl;
printVtable(pB, "BaseB", 2); // funcB, ~BaseB
// 验证:通过不同基类指针调用虚函数
cout << "--- 通过不同基类指针调用虚函数 ---" << endl;
pA->funcA(); // MultiDerived::funcA()
pB->funcB(); // MultiDerived::funcB()
// 验证:指针转换时的地址调整
cout << "\n--- 指针转换时的地址调整 ---" << endl;
cout << " &md = " << &md << endl;
cout << " (BaseA*)&md = " << static_cast<BaseA*>(&md) << endl;
cout << " (BaseB*)&md = " << static_cast<BaseB*>(&md) << endl;
cout << " 注意:BaseB* 的地址与对象起始地址不同!" << endl;
}
// ============================================================
// 第三部分:虚析构函数的必要性
// ============================================================
class NoVirtualDestructor {
public:
~NoVirtualDestructor() { // 不是虚析构函数!
cout << " NoVirtualDestructor 析构" << endl;
}
};
class DerivedNoVirtual : public NoVirtualDestructor {
public:
~DerivedNoVirtual() {
cout << " DerivedNoVirtual 析构" << endl;
}
};
class WithVirtualDestructor {
public:
virtual ~WithVirtualDestructor() { // 虚析构函数
cout << " WithVirtualDestructor 析构" << endl;
}
};
class DerivedWithVirtual : public WithVirtualDestructor {
public:
~DerivedWithVirtual() override {
cout << " DerivedWithVirtual 析构" << endl;
}
};
void demo_virtual_destructor() {
cout << "\n===== 虚析构函数的必要性 =====" << endl;
// 1. 非虚析构函数的问题
cout << "\n--- 非虚析构函数(有问题)---" << endl;
cout << " 通过基类指针 delete 派生类对象:" << endl;
NoVirtualDestructor* p1 = new DerivedNoVirtual();
delete p1;
// 注意:只调用了 NoVirtualDestructor 析构!
// DerivedNoVirtual 析构没有被调用 → 资源泄漏!
// 2. 虚析构函数的正确行为
cout << "\n--- 虚析构函数(正确)---" << endl;
cout << " 通过基类指针 delete 派生类对象:" << endl;
WithVirtualDestructor* p2 = new DerivedWithVirtual();
delete p2;
// 正确:先调用 DerivedWithVirtual 析构,再调用 WithVirtualDestructor 析构
cout << "\n--- 总结 ---" << endl;
cout << " 非虚析构:只调用基类析构,派生类资源泄漏" << endl;
cout << " 虚析构:先派生类析构,再基类析构,资源正确释放" << endl;
}
// ============================================================
// 第四部分:构造/析构中的虚函数调用
// ============================================================
class BaseVFunc {
public:
BaseVFunc() {
cout << " BaseVFunc 构造开始" << endl;
virtualFunc(); // 在构造函数中调用虚函数
cout << " BaseVFunc 构造结束" << endl;
}
virtual void virtualFunc() const {
cout << " BaseVFunc::virtualFunc() —— 在构造函数中被调用" << endl;
}
virtual ~BaseVFunc() {
cout << " BaseVFunc 析构开始" << endl;
virtualFunc(); // 在析构函数中调用虚函数
cout << " BaseVFunc 析构结束" << endl;
}
};
class DerivedVFunc : public BaseVFunc {
public:
DerivedVFunc() {
cout << " DerivedVFunc 构造开始" << endl;
virtualFunc();
cout << " DerivedVFunc 构造结束" << endl;
}
void virtualFunc() const override {
cout << " DerivedVFunc::virtualFunc()" << endl;
}
~DerivedVFunc() override {
cout << " DerivedVFunc 析构开始" << endl;
virtualFunc();
cout << " DerivedVFunc 析构结束" << endl;
}
};
void demo_virtual_in_ctor_dtor() {
cout << "\n===== 构造/析构中的虚函数调用 =====" << endl;
cout << "\n--- 创建 DerivedVFunc 对象 ---" << endl;
DerivedVFunc d;
cout << "\n--- 销毁 DerivedVFunc 对象 ---" << endl;
// d 离开作用域
cout << "\n--- 分析 ---" << endl;
cout << " 在基类构造函数中调用虚函数 → 调用基类版本(不是派生类版本)" << endl;
cout << " 在基类析构函数中调用虚函数 → 调用基类版本(不是派生类版本)" << endl;
cout << " 原因:构造基类部分时,派生类部分尚未构造,vptr 指向基类 vtable" << endl;
cout << " 析构基类部分时,派生类部分已经析构,vptr 指向基类 vtable" << endl;
}
// ============================================================
// main 函数
// ============================================================
int main() {
cout << "========================================" << endl;
cout << " 虚函数深度剖析 —— 完整示例" << endl;
cout << " 作者:青松与桑叶" << endl;
cout << "========================================" << endl;
demo_single_inheritance_vtable();
demo_multiple_inheritance_vptr();
demo_virtual_destructor();
demo_virtual_in_ctor_dtor();
cout << "\n========== 程序结束 ==========" << endl;
return 0;
}