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

使用std::dynamic_pointer_cast触发段错误,求原因解析

问题分析与解决

你的代码触发段错误的核心原因是对象切片导致std::dynamic_pointer_cast转型失败返回nullptr,随后你直接对空指针调用成员函数引发了未定义行为。

具体问题拆解

我们先看关键的一行代码:

std::shared_ptr<foo> fptr = std::make_shared<foo>(b);

这里你用bar类型的对象b去构造一个foo类型的对象,因为bar是foo的子类,C++会执行对象切片操作:它只会把b中属于基类foo的成员(也就是x)拷贝到新创建的foo对象里,完全丢弃bar特有的成员y。最终fptr指向的是一个纯粹的foo对象,和原来的bar对象没有任何关系。

而std::dynamic_pointer_cast的作用是在继承体系中做安全的向下转型,它要求被转型的指针实际指向的是目标子类类型的对象。现在fptr指向的是foo对象,不是bar对象,所以转型失败,返回nullptr。

接下来你直接执行:

std::cout << (std::dynamic_pointer_cast<bar>(fptr))->get_x();

对nullptr调用->操作符属于未定义行为,这就是段错误的直接原因。

修复方案

1. 避免对象切片,让智能指针实际指向bar对象

如果你想通过基类智能指针管理子类对象,应该直接创建子类的shared_ptr再赋值给基类指针:

std::shared_ptr<foo> fptr = std::make_shared<bar>(0.5);

这样fptr指向的实际是bar对象,std::dynamic_pointer_cast<bar>就能成功返回有效的智能指针。

2. 始终检查转型结果是否有效

不管什么时候使用dynamic_pointer_cast,都应该先检查返回值是否为nullptr,避免空指针访问:

if (auto bar_ptr = std::dynamic_pointer_cast<bar>(fptr)) {
    std::cout << bar_ptr->get_x() << std::endl;
} else {
    std::cout << "Failed to cast to bar!" << std::endl;
}

完整修复后的代码

#include <iostream>
#include <memory>
class foo {
private:
    int x;
public:
    foo() : x(0) {}
    foo(int xx) : x(xx) {}
    virtual ~foo() = default;
    int get_x() const { return x; }
};
class bar : public foo {
private:
    double y;
public:
    bar(double yy) : foo(), y(yy) {}
    double get_y() const { return y; }
};
int main(void) {
    std::shared_ptr<foo> fptr = std::make_shared<bar>(0.5);
    if (auto bar_ptr = std::dynamic_pointer_cast<bar>(fptr)) {
        std::cout << bar_ptr->get_x();
    } else {
        std::cout << "Cast failed!" << std::endl;
    }
    return 0;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 07:14:47