题目

编写程序,演示 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