农场模拟器中dynamic_cast判断Produce派生类类型失效问题求助
问题根源与解决方案
你的核心问题是对象切片,这是C++多态编程里的典型陷阱:
为什么之前的代码始终失败?
看你的Farmland类定义,成员planted是Produce类型的实体对象,而非指针或引用。当你把Crops/Animals这类派生类对象赋值给它时,C++会只拷贝派生类中属于基类Produce的部分,派生类特有的数据、虚函数表都会被"切掉"——此时planted本质就是一个纯Produce对象,和你原本的Crops完全无关。
不管你是把它赋值给局部变量、返回引用还是返回指针,最终操作的都是这个被切片后的基类对象,dynamic_cast自然无法将它转换成Crops*。
修复方案
1. 修改Farmland的成员类型
把planted改成指针类型(或智能指针),才能存储派生类对象的地址,保留多态特性:
裸指针版本(需手动管理内存)
class Farmland{ protected: bool empty_or_used; bool unlocked; Produce* planted; // 改为指针 public: // 构造函数初始化指针为空 Farmland() : empty_or_used(true), unlocked(false), planted(nullptr) {} bool getEmptyOrUsed(); void setEmptyOrUsed(bool a); bool getUnlocked(); Produce* getPlanted() { return planted; } void setUnlocked(bool b); void setProduce(Produce* newPlanted) { planted = newPlanted; empty_or_used = (planted != nullptr); } // 析构函数释放内存,避免泄漏 ~Farmland() { delete planted; } };
智能指针版本(自动管理内存,推荐)
#include <memory> class Farmland{ protected: bool empty_or_used; bool unlocked; std::unique_ptr<Produce> planted; public: Farmland() : empty_or_used(true), unlocked(false) {} bool getEmptyOrUsed(); void setEmptyOrUsed(bool a); bool getUnlocked(); Produce* getPlanted() { return planted.get(); } void setUnlocked(bool b); void setProduce(std::unique_ptr<Produce> newPlanted) { planted = std::move(newPlanted); empty_or_used = (planted != nullptr); } // 智能指针无需手动编写析构函数 };
2. 正确使用dynamic_cast
修改后,给Farmland设置作物/动物时,要传入派生类的指针/智能指针:
// 示例:创建Crops对象并绑定到Farmland Farmland lands[10]; // 裸指针版本 lands[0].setProduce(new Crops()); // 智能指针版本 lands[0].setProduce(std::make_unique<Crops>()); // 遍历执行生长逻辑 for(int i = 0; i < 10; ++i){ Produce* ptr = lands[i].getPlanted(); if(Crops* crops = dynamic_cast<Crops*>(ptr)){ // 执行Crops的生长操作 crops->grow(); } }
额外注意事项
- 确保
Produce类至少有一个虚函数(你已满足该条件),否则dynamic_cast无法工作——多态的实现依赖虚函数表。 - 裸指针需要注意内存安全,避免重复释放或泄漏;智能指针能自动处理这些问题,优先选用。
内容的提问来源于stack exchange,提问作者mg763
相关产品推荐
相关产品推荐

