C++中派生类存入基类IngameObject指针vector后类型异常问题
核心错误
你遇到的问题由三个错误共同导致:
- 你自定义的
instanceof是编译期静态类型判断,而非运行期实际对象类型判断。模板推导仅依赖输入参数的静态类型:存入vector前指针的静态类型是Character*,所以判断为真;存入vector后元素的静态类型是IngameObject*,模板推导的T就是IngameObject,std::is_base_of<Character, IngameObject>自然返回假,和指针实际指向的对象类型无关。 - 子类
Character重定义了和父类同名的clickable成员变量,属于名字隐藏,不是类成员重写。两个类的clickable是完全独立的两个变量,用父类指针访问时只会读取父类的clickable值,因此拿到的是默认的false。 - 基类
IngameObject没有定义虚函数,不满足C++运行期类型识别(RTTI)的要求,也会导致后续动态类型判断、内存释放时出现问题。
修复方案
1. 替换instanceof为运行期动态类型判断
用dynamic_cast实现运行期类型校验,要求基类为多态类型:
template<typename Derived, typename Base> inline bool instanceof(const Base* ptr) { return dynamic_cast<const Derived*>(ptr) != nullptr; }
2. 改造类结构,移除同名隐藏,给基类添加虚函数
给基类添加虚析构函数满足多态要求,子类构造时直接修改父类的clickable成员,不要重新定义同名变量:
class IngameObject { public: // 虚析构函数是多态类的标配,也能避免后续释放对象时内存泄漏 virtual ~IngameObject() = default; protected: bool clickable = false; // 新增构造函数供子类初始化父类成员 IngameObject(bool clickable_) : clickable(clickable_) {} }; class Character : public IngameObject { public: // 你的原有构造参数后面加初始化列表,给父类传clickable=true Character(/* 原有参数:纹理、矩形、坐标等 */) : IngameObject(true) { // 原有构造逻辑不变 } };
3. 确认编译选项开启RTTI
绝大多数桌面端编译器默认开启RTTI支持,若为嵌入式编译环境可手动开启对应编译选项。
修复后你再运行测试代码,两次instanceof判断都会返回真,clickable的值也会符合预期。
内容的提问来源于stack exchange,提问作者Rosta6
相关产品推荐
相关产品推荐

