调用TexturedSpritesheet::Render为何未触发其重写的UpdateBuffers?
问题分析与解决方案
你遇到的这个问题是C++中函数隐藏和多态重写的典型坑点,我来给你拆解清楚:
问题根源
你的基类TexturedRect中的UpdateBuffers两个重载函数都没有声明为virtual,这就导致:
- 派生类
TexturedSpritesheet中定义的同名UpdateBuffers函数,并不是对基类函数的多态重写,而是直接隐藏了基类的版本。 - 当基类的
Render函数调用UpdateBuffers时,它只会调用基类自己的UpdateBuffers实现,不会根据对象的实际类型(派生类)动态绑定到派生类的重写版本——因为没有虚函数机制的支持。
修复步骤
1. 把基类的UpdateBuffers声明为虚函数
修改TexturedRect.h中的函数声明,给两个UpdateBuffers加上virtual关键字:
public: bool Render(ID3D11DeviceContext*, int, int); bool Render(ID3D11DeviceContext*, int, int, DirectX::XMFLOAT4); protected: // 加上virtual,启用多态 virtual bool UpdateBuffers(ID3D11DeviceContext*, int, int); virtual bool UpdateBuffers(ID3D11DeviceContext*, int, int, DirectX::XMFLOAT4);
2. 派生类重写时加上override关键字
修改TexturedSpritesheet.h中的函数声明,加上override关键字(这一步是可选但强烈推荐的,能帮你在编译期就检查出函数签名不匹配的问题):
protected: // 用override明确表示这是重写基类的虚函数 bool UpdateBuffers(ID3D11DeviceContext*, int, int) override; bool UpdateBuffers(ID3D11DeviceContext*, int, int, DirectX::XMFLOAT4) override;
原理补充
C++中,只有当基类函数被声明为virtual时,编译器才会为该函数生成虚函数表(vtable),运行时会根据对象的实际类型(而非指针/引用的静态类型)来调用对应的派生类重写版本。如果没有virtual,派生类的同名函数会直接隐藏基类的所有同名重载,基类中的调用只会指向自己的实现。
这样修改之后,当你调用TexturedSpritesheet::Render时,就会正确触发派生类重写的UpdateBuffers了。
内容的提问来源于stack exchange,提问作者user4164047
相关产品推荐
相关产品推荐

