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

C++中通过基类指针调用基类方法如何访问派生类新增的数据

崩溃原因

你猜测的原因不对,drawable是基类的protected成员,派生类向其中插入指针、基类draw方法读取的是同一个向量,这部分逻辑没有问题。崩溃的核心原因是你初始化player成员的写法触发了野指针:
你在Level构造函数中写的player = Player(500.f, 500.f)会先生成一个临时的Player对象,临时对象的构造函数会把自己内部shape的地址插入自身的drawable向量。之后调用默认赋值运算符把临时对象的内容浅拷贝给成员变量player,临时对象随即销毁,此时player的drawable向量里保存的是已经销毁的临时对象的shape地址,属于悬垂指针,调用draw方法访问这块内存就会触发崩溃。

解决方案

1. 改用成员初始化列表初始化成员

直接在Level构造函数的初始化列表中构造player,避免生成临时对象:

Level::Level() : player(500.f, 500.f)
{
    gameObjects.push_back(&player);
}

这种方式会直接调用成员player的构造函数,drawable中插入的就是成员player自身shape的地址,只要player的生命周期和Level一致,指针就不会失效。

2. 禁止基类及派生类的拷贝/移动操作

因为你的类中存储了指向自身成员的指针,一旦发生拷贝、移动操作,指针就会失效,建议直接在基类中删除相关操作,从编译层面避免误写:

class GameObject
{
public:
    GameObject() = default;
    // 禁止拷贝、移动
    GameObject(const GameObject&) = delete;
    GameObject& operator=(const GameObject&) = delete;
    GameObject(GameObject&&) = delete;
    GameObject& operator=(GameObject&&) = delete;
    // 添加虚析构,保证基类指针销毁派生类对象时能正确调用派生类析构
    virtual ~GameObject() = default;
protected:
    std::vector<Drawable*> drawable;
// ...
};

加了上述声明后,你之前写的player = Player(...)会直接编译报错,避免运行时才发现问题。

3. 可选:如需支持拷贝可自定义虚更新接口

如果你的业务场景需要支持派生类的拷贝、移动,可以在基类中声明虚接口,派生类自行实现更新drawable向量的逻辑,拷贝后调用该接口刷新指针即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.07 11:54:04