我对问题标题不满意,但无法很好地描述它。为了简洁起见,我将实现放在类声明中。
我有一个这样的课:
class VisibleObject {
public:
void draw(sf::RenderWindow& rw) {
rw.draw(*shape.get());
}
virtual void setSize(sf::Vector2f) = 0;
protected:
std::shared_ptr<sf::Shape> shape;
}
sf::Shape
是一个抽象类。然后,我有一个派生类,如下所示:
class Brick : VisibleObject {
Brick() {
shape.reset(new sf::RectangleShape());
}
void setSize(sf::Vector2f newSize) {
std::dynamic_pointer_cast<sf::RectangleShape>(shapes).get()->setSize(newSize);
}
}
sf::RectangleShape()
是一个具体的类,它继承自sf::Shape
并setSize()
为其定义,而不是sf::Shape
,这就是为什么我需要强制转换。
当然,在动态转换失败并返回空的shared_ptr的情况下,我需要进行一些错误处理。
之所以这样做,是因为我希望能够draw
一次定义该方法,因为在这个简单的游戏中,每个对象都将以这种方式绘制其成员。最初,我将形状保留在基类之外,例如Brick拥有自己的私有对象sf::RectangleShape
,可以在堆栈中实例化该私有对象。这很干净,但是随后必须针对每种对象类型重新编写draw方法。
这可行,但使用起来较麻烦,并引入了堆分配。我也有shared_ptr
开销(我会用过unique_ptr
,但我需要动态转换)。
这是做我想做的最合适的方法吗?
除了不要求在中存储std::shared_ptr<sf::Shape>
,为什么不简单地引入一种sf::Shape&
从具体类中检索的方法?
class VisibleObject {
virtual sf::Shape& getShape() = 0;
public:
void draw(sf::RenderWindow& rw) {
rw.draw(getShape());
}
virtual void setSize(sf::Vector2f) = 0;
};
class Brick : VisibleObject {
sf::RectangleShape shape;
sf::Shape& getShape() override { return shape; }
public:
void setSize(sf::Vector2f newSize) override {
shape.setSize(newSize);
}
};
当您只可以存储一个普通的旧成员时,通过指向基础的指针进行存储似乎很荒谬,从而引入了间接寻址和向下转换以及引用计数开销。实际上,如果我正确地理解了该问题,则可以使用模板来生成具体的类,并避免大量重复使用:
class VisibleObject {
public:
virtual ~VisibleObject() {}
virtual void draw(sf::RenderWindow&) = 0;
virtual void setSize(sf::Vector2f) = 0;
};
template <typename Shape>
class VisibleConcreteObject : public VisibleObject {
Shape shape;
public:
void draw(sf::RenderWindow& rw) override /* final? */ {
rw.draw(shape);
}
void setSize(sf::Vector2f newSize) override /* final? */ {
shape.setSize(newSize);
}
};
typedef VisibleConcreteObject<sf::RectangleShape> Brick;
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句