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

为何引用未创建的派生类指针合法且不属于未定义行为?

C++中基类指针转未构造派生类指针的合法性与未定义行为分析

先看示例代码:

#include <iostream>

struct A{
    int a;
     void foo() {
        std::cout << "A = " << a << std::endl;
     }
};

struct B : public A{
    int b;
    void foo() {
        std::cout << "B = " << b << std::endl;
    }
};


int main() {
    A *a = new A();
    B *b = static_cast<B*>(a);

    a->foo(); // 输出 A = 0
    b->foo(); // 输出 B = 0
    
    b->b = 333;
    
    b->foo(); // 输出 B = 333
    a->foo(); // 输出 A = 0
}

核心问题拆解

  1. 指针转换操作本身的合法性
    static_cast<B*>(a)这个转换在public继承场景下是C++标准允许的语法,但这只是编译期允许的转换——得到的指针并不指向真正的B类型对象,因为我们只构造了A的实例,内存中根本没有B独有的b成员对应的空间。

  2. 后续操作的未定义行为

  • 调用b->foo():因为foo是非虚函数,调用是编译期绑定的,编译器直接生成调用B::foo的代码。但B::foo中访问的b成员,对应的是A对象内存之后的未知区域,第一次读取到0是随机的未初始化内存值,而b->b = 333则是越界修改不属于当前对象的内存,这两种操作都属于明确的未定义行为。
  • 你看到的输出"正常"只是巧合,换不同编译器、优化级别或运行环境,可能出现崩溃、乱码、程序异常终止等任意结果。
  1. 结论
    基类指针强转为派生类指针的操作本身不是未定义行为,但通过这个指针访问派生类独有的成员、或是在虚函数机制下调用成员函数,都属于未定义行为。这种写法完全依赖不可靠的内存巧合,绝对不能出现在生产代码中。

内容的提问来源于stack exchange,提问作者zizeca

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 02:50:38