虚函数、虚函数表和 type_info共同构成了 C++ 运行时多态和类型识别的核心机制。
虚函数表 - “餐厅菜单系统”
现实比喻
想象一家多主题餐厅:
- 每个餐桌有一个菜单架(虚函数表指针)
- 不同主题区域有不同的菜单(虚函数表)
- 顾客点菜时,看菜单架找到对应菜单
代码示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| class Restaurant { public: virtual void 特色菜() { cout << "普通套餐" << endl; } virtual void 甜点() { cout << "水果拼盘" << endl; } virtual ~Restaurant() {} };
class 中餐厅 : public Restaurant { public: void 特色菜() override { cout << "北京烤鸭" << endl; } void 甜点() override { cout << "芝麻汤圆" << endl; } };
class 西餐厅 : public Restaurant { public: void 特色菜() override { cout << "牛排" << endl; } void 甜点() override { cout << "提拉米苏" << endl; } };
|
内存布局
1 2 3 4 5 6 7 8 9 10 11 12
| 中餐厅 餐厅1; 西餐厅 餐厅2;
Restaurant* 当前餐厅 = &餐厅1; 当前餐厅->特色菜();
当前餐厅 = &餐厅2; 当前餐厅->特色菜();
|
type_info - “身份证识别系统”
现实比喻
想象一个人员管理系统:
- 每个人有身份证(type_info)
- 系统可以检查:“这是学生吗?” “这是老师吗?”
- 用于安全地确定人员类型
代码示例
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
| #include <typeinfo>
class 人员 { public: virtual ~人员() {} };
class 学生 : public 人员 { public: void 学习() { cout << "正在学习" << endl; } };
class 老师 : public 人员 { public: void 教学() { cout << "正在教学" << endl; } };
void 处理人员(人员* 某人) { cout << "实际类型: " << typeid(*某人).name() << endl; if (typeid(*某人) == typeid(学生)) { cout << "这是一个学生" << endl; static_cast<学生*>(某人)->学习(); } else if (typeid(*某人) == typeid(老师)) { cout << "这是一个老师" << endl; static_cast<老师*>(某人)->教学(); } }
|
两者配合使用 - dynamic_cast 的工作原理
完整系统比喻
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| 人员* 未知人员 = 获取未知人员();
if (学生* 学生指针 = dynamic_cast<学生*>(未知人员)) { 学生指针->学习(); } else if (老师* 老师指针 = dynamic_cast<老师*>(未知人员)) { 老师指针->教学(); } else { cout << "未知人员类型" << endl; }
|
实际内存结构可视化
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
| class Animal { public: virtual void speak() = 0; virtual ~Animal() {} };
class Dog : public Animal { public: void speak() override { cout << "Woof!" << endl; } void fetch() { cout << "Fetching ball" << endl; } };
class Cat : public Animal { public: void speak() override { cout << "Meow!" << endl; } void climb() { cout << "Climbing tree" << endl; } };
Dog dog;
Cat cat;
|
实际应用场景
场景1:游戏角色系统
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
| class 游戏角色 { public: virtual void 攻击() = 0; virtual ~游戏角色() {} };
class 战士 : public 游戏角色 { public: void 攻击() override { cout << "剑攻击" << endl; } void 盾牌格挡() { cout << "格挡攻击" << endl; } };
class 法师 : public 游戏角色 { public: void 攻击() override { cout << "火球术" << endl; } void 治疗() { cout << "恢复生命" << endl; } };
void 处理战斗(游戏角色* 角色) { 角色->攻击(); if (auto 战士指针 = dynamic_cast<战士*>(角色)) { 战士指针->盾牌格挡(); } else if (auto 法师指针 = dynamic_cast<法师*>(角色)) { 法师指针->治疗(); } }
|
总结比喻
-
虚函数表 = 餐厅菜单系统
- 每个餐厅类型有自己的菜单
- 顾客通过菜单架找到正确菜单
- 实现"不同对象,相同接口,不同行为"
-
type_info = 身份证识别系统
- 每个人有唯一身份证
- 系统可以安全地识别人员类型
- 防止"让学生去教书"这样的错误
两者配合实现了C++的多态性和安全的运行时类型识别!