SFML如何设置sf::Drawable位置 指针访问setPosition报错解决
问题原因
sf::Drawable是SFML提供的纯接口基类,仅声明了纯虚方法draw,本身不包含setPosition、setRotation、setScale这类变换操作相关的成员方法。
IDE报No member named 'setPosition' in 'sf::Drawable'警告是符合预期的:位置、缩放、旋转这类变换接口实际定义在sf::Transformable类中。SFML内置的可绘制对象(sf::Sprite、sf::Text、sf::Shape等)都是同时继承sf::Drawable和sf::Transformable两个类,用sf::Drawable*类型指针存储对象时,编译器只能识别Drawable接口部分的方法,自然访问不到Transformable中定义的变换接口。
额外提醒:当前代码中的view指针未初始化,属于野指针,就算解决了方法访问问题,直接调用成员方法也会触发运行时崩溃,使用前必须为其分配具体类型的对象实例。
可行解决方案
- 方案1:如果View类只会固定存储某一种具体的SFML可绘制对象,直接把成员指针的类型替换为对应具体类型即可。比如存储的是精灵对象,就把成员定义为
sf::Sprite* view;,此时可以直接调用该类型的所有公有方法,包括位置设置相关接口。 - 方案2:如果需要存储不同类型的SFML内置可绘制对象,可以在调用变换方法前,将指针安全转换为
sf::Transformable*类型,前提是能保证指针指向的对象确实继承自sf::Transformable:
#include <SFML/Graphics.hpp> class View{ public: View(){ // 先初始化指针,分配具体类型对象 view = new sf::Sprite(); // 转换为Transformable指针调用变换方法 static_cast<sf::Transformable*>(view)->setPosition(200.f, 200.f); } protected: sf::Drawable *view; };
- 方案3:自定义合并两个基类的通用接口,后续所有需要存入view指针的可绘制对象都继承自这个自定义基类,就可以直接同时调用draw方法和变换方法,不需要额外类型转换:
#include <SFML/Graphics.hpp> // 自定义可变换、可绘制的统一基类 class ITransformableDrawable : public sf::Drawable, public sf::Transformable { public: // 保留纯虚draw方法,强制子类实现绘制逻辑 void draw(sf::RenderTarget& target, sf::RenderStates states) const override = 0; }; class View{ public: View(){ // view指向继承ITransformableDrawable的具体子类实例 view->setPosition(200.f, 200.f); // 可直接调用变换方法 } protected: ITransformableDrawable *view; };
注意:做类型转换时不要使用C风格强制转换,必须确认指针指向的对象实际继承了目标类型,否则会触发未定义行为。
内容的提问来源于stack exchange,提问作者Saleh Soleymani
相关产品推荐
相关产品推荐

