题目
编写程序,演示 C++ 的 RTTI(Run-Time Type Information 运行时类型识别)与 dynamic_cast 向下安全转型(Downcasting)。设计基类 Entity 与派生类 Player、Monster。对比传统 C 风格裸强制转换导致的内存越界假阳性;利用 dynamic_cast 校验转换合法性:指针类型转换失败返回 nullptr、引用类型转换失败抛出 std::bad_cast 异常。
输入格式:无需外部输入。
输出格式:输出针对指针与引用的 dynamic_cast 转型判定与异常捕获流水。
数据范围与约定:RTTI 机制、typeid 类型名称、安全向下类型转换。
思路与算法
1. RTTI 的工作前提dynamic_cast 能够进行运行时安全类型核查的先决条件是:基类必须至少包含一个 virtual 虚函数(即具有多态性)。因为类型元信息(type_info 指针)是存放在虚函数表(vtable)的负偏移位置的!
2. 指针转型安全模式
对指针进行向下转型:auto p = dynamic_cast<Derived*>(basePtr);。若类型不匹配,安全返回 nullptr,通过 if (p) 完成安全分支分流。
3. 引用转型异常模式
因为在 C++ 中“不存在空引用”,所以对引用进行 dynamic_cast<Derived&>(baseRef) 失败时,无法返回空,只能抛出 std::bad_cast 异常。
完整程序
#include <iostream>
#include <string>
#include <typeinfo>
class Entity {
public:
virtual ~Entity() = default; // 必须有虚函数以开启 RTTI
virtual void update() { std::cout << "Entity 更新\n"; }
};
class Player : public Entity {
public:
void attack() { std::cout << " [Player 技能] 玩家释放极光斩杀技能!\n"; }
};
class Monster : public Entity {
public:
void roar() { std::cout << " [Monster 动作] 怪物发出狂暴怒吼!\n"; }
};
void identifyAndExecute(Entity* entity) {
std::cout << "正在识别实体运行时类型: "
<< (dynamic_cast<Player*>(entity) ? "Player" :
(dynamic_cast<Monster*>(entity) ? "Monster" : "Entity")) << "\n";
// 1. 指针类型 dynamic_cast 向下安全探测
if (Player* p = dynamic_cast<Player*>(entity)) {
p->attack();
} else if (Monster* m = dynamic_cast<Monster*>(entity)) {
m->roar();
} else {
std::cout << " 未知实体类型\n";
}
}
int main() {
Player playerObj;
Monster monsterObj;
std::cout << "--- 1. 指针向下转型探测测试 ---\n";
identifyAndExecute(&playerObj);
identifyAndExecute(&monsterObj);
std::cout << "\n--- 2. 引用向下转型失败捕获测试 ---\n";
Entity& wrongRef = monsterObj; // 实际上是 Monster
try {
std::cout << "尝试强转为 Player& (非合法类型)...\n";
Player& pRef = dynamic_cast<Player&>(wrongRef);
pRef.attack();
} catch (const std::bad_cast& e) {
std::cout << "【捕获异常】引用向下转型失败: std::bad_cast\n";
(void)e;
}
return 0;
}运行示例
输出:
--- 1. 指针向下转型探测测试 ---
正在识别实体运行时类型: Player
[Player 技能] 玩家释放极光斩杀技能!
正在识别实体运行时类型: Monster
[Monster 动作] 怪物发出狂暴怒吼!
--- 2. 引用向下转型失败捕获测试 ---
尝试强转为 Player& (非合法类型)...
【捕获异常】引用向下转型失败: std::bad_cast