C++对象从函数返回后类型信息变为基类的原因是什么?
前提说明
你给出的示例代码存在一处笔误:第一处typeid(derived)的操作数是std::shared_ptr<Derived>类型的智能指针对象,正常输出应为智能指针的类型名而非Derived,因此以下分析默认你实际代码中该处为typeid(*derived).name(),即对智能指针指向的派生类对象做类型识别。
同时你给出的示例代码本身存在严重未定义行为:makeDerived中的局部std::shared_ptr<Derived>会在函数返回时析构,若没有其他智能指针持有指向的Derived对象,对象会被释放,返回的Base&是悬空引用,main中对该引用的所有操作(包括typeid调用)结果均不可预期,这很可能是你无法稳定复现问题的核心原因。
会出现输出Derived, Base的几种常见情况
- Base类不具备多态性
C++标准明确规定:只有当typeid的操作数是多态类类型(类中至少定义了一个虚函数)的glvalue时,才会触发运行时动态类型识别,否则直接返回表达式的静态类型对应的type_info。
若你的Base类没有定义任何虚函数,那么main中typeid(derived)的操作数静态类型是Base&,会直接返回Base的类型信息;而makeDerived中typeid(*derived)的静态类型是Derived,返回Derived的类型信息,完全符合你遇到的输出结果。 - 返回的引用实际绑定到了
Base类型的对象
若secondLayer返回的智能指针实际指向的是Base类的实例,你通过不安全的指针转换(比如static_pointer_cast、C风格强转)将其赋值给了std::shared_ptr<Derived>,那么引用绑定的对象本身就是Base类型,typeid自然返回Base的类型信息。 - RTTI被禁用或被破坏
若你开启了关闭运行时类型识别的编译选项(比如GCC/Clang的-fno-rtti),typeid的动态识别功能会失效,只会返回表达式的静态类型;另外悬空引用导致的内存越界、对象析构后内存被复用为Base对象等内存错误,也可能破坏RTTI信息,导致输出异常。
内容的提问来源于stack exchange,提问作者karobar
相关产品推荐
相关产品推荐

