You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++将指向派生类的基类指针转为同基另一派生类指针为何不崩溃

问题相关代码
#include <iostream>

class Entity
{
private:
    int entityInt_;

public:
    Entity()
        : entityInt_(0)
    {}

    virtual void print() const
    {
        std::cout << "This is Entity class\n";
    }
};

class Player : public Entity
{
private:
    int playerInt_;

public:
    Player()
        : playerInt_(0)
    {}

    void print() const
    {
        std::cout << "This is Player class\n";
    }
};

class Enemy : public Entity
{
private:
    int enemyInt_;
    double enemyFloat_;

public:
    Enemy()
        : enemyInt_(0), enemyFloat_(0.0)
    {}

    void exclusiveEnemy() const
    {
        std::cout << "This is an exclusive method of Enemy class\n";
    }

    void print() const
    {
        std::cout << "This is Enemy class\n";
    }
};

int main(int argc, const char* argv[])
{
    Entity* actuallyPlayer = new Player();
    Enemy* enemy = static_cast<Enemy*>(actuallyPlayer);

    enemy->print();
    enemy->exclusiveEnemy();
}
原因解释

你给出的代码本质属于C++未定义行为(Undefined Behavior),看起来运行正常只是特定编译、运行环境下的巧合,不代表代码逻辑合法,换编译选项、编译器或者运行环境随时可能崩溃、输出异常结果。

没有崩溃的具体原因可以分为三点:

  • static_cast<Enemy*>(actuallyPlayer)这个向下转型本身就不合法:static_cast做类指针向下转型时不会做运行时类型检查,编译器默认你保证指针指向的内存确实是目标类型Enemy的实例,你现在实际指向的是Player实例,这一步就已经触发未定义行为。
  • 调用enemy->exclusiveEnemy()未崩溃的原因:这个方法是非虚成员函数,且实现中没有访问任何Enemy类的非静态成员变量。非虚成员函数本质是带隐式this参数的普通全局函数,只要调用过程中没有读写this指向的内存数据,哪怕this指针指向非法内存,也不会触发访问异常,这里函数只是输出固定字符串,完全没用到成员变量,所以运行正常。
  • 调用enemy->print()输出This is Enemy class的原因:print是虚函数,正常来说应该根据对象实际类型的虚表调用对应实现,但你的代码属于未定义行为,编译器有权做任意处理。大概率是你的编译器做了优化,认为通过Enemy*类型指针调用print可以跳过虚表查询,直接静态绑定到Enemy::print实现,所以输出了Enemy的打印内容,这也是未定义行为的一种表现。

如果需要安全做向下转型,应该使用dynamic_cast,会在转型失败时返回空指针(针对指针类型)或者抛出异常(针对引用类型),避免出现这类非法访问问题。


内容的提问来源于stack exchange,提问作者David Pérez Sánchez

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 08:45:03