在抽象基类中与抽象类成员合作的最佳方法
Best way to work with an abstract class member in an abstract base class?
我对问题标题不满意,但我无法很好地描述它。为了简洁起见,我将实施在班级声明中。
我有这样的课程:
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
,这就是为什么我需要施放。
当然,如果动态铸件失败并返回一个空的共享_ptr。
,我需要做一些错误处理。我这样做是因为我希望能够仅定义draw
方法一次,因为在这个简单的游戏中,每个对象都会以这种方式绘制其成员。最初,我将形状排除在基类之外,例如砖只有自己的私人sf::RectangleShape
可以在堆栈上实例化;这很干净,但是必须针对每种对象类型重写绘图方法。
这起作用,但与之合作并引入了堆分配更丑陋。我也有shared_ptr
开销(我会使用unique_ptr
,但我需要动态铸造)。
这是最合适的方法来做我要做的事情吗?
可能最好将接口保持接口,而不是开始强制执行实现详细信息。因此,只要拥有一个空的基类:
class VisibleObject
{
public:
~VisibleObject() {}
virtual void draw(sf::RenderWindow & window) = 0;
virtual void setSize(sf::Vector2f const & size) = 0;
};
您可以将形状存储粘贴到实现此接口的混凝土类中。
此外,Shape
应该提供虚拟调整大小方法:
class Shape
{
public:
virtual ~Shape() {}
virtual void resize(sf::Vector2f const & size) = 0;
};
现在,您可以将VisibleShapeObject
作为中间级类别进行:
class VisibleShapeObject : public VisibleObject
{
public:
virtual void draw(sf::RenderWindow & window) override final
{
window.draw(*shape_);
}
virtual void setSize(sf::Vector2f const & size) override final
{
shape_->resize(size);
}
protected:
std::shared_ptr<Shape> shape_; // or unique_ptr<Shape>
};
而不是在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;
您尚未共享您要做的一切,但这是一种方法:
template<ShapeT>
class VisibleObject {
public:
void draw(sf::RenderWindow& rw) {
rw.draw(*shape.get());
}
virtual void setSize(sf::Vector2f) = 0;
protected:
std::shared_ptr<ShapeT> shape;
void reset(ShapeT* shape) {
this->shape = shape;
}
}
class Brick : VisibleObject<sf::RectangleShape> {
Brick() {
shape.reset(new sf::RectangleShape());
}
void setSize(sf::Vector2f newSize) {
shape->setSize(newSize);
}
}
可能有原因为什么这对您不起作用,但是没有更多的见解,我无法猜测什么。
- 在C#中处理C++指针而不使用unsafe的最佳方法
- 在C++中,将大的无符号浮点数四舍五入为整数的最佳方法是什么
- 实现无开销push_back的最佳方法是什么
- 在C++中向零方向近似的最佳方法
- 使用不同的CRT将新的C++代码与旧的(二进制)组件隔离开来的最佳方法是什么
- 检测win32服务创建和删除的最佳方法
- 在C++中样板"冷/never_inline"错误处理技术的最佳方法是什么?
- 在 c++ 中对类中的 c 字符串动态数组进行排序的最佳方法是什么?
- 将线程中的数据存储到全局容器的最佳方法?
- 将一系列整数放入类的最佳方法是什么?
- 在派生类中使用基类的私有成员变量的最佳方法
- 在 C++ 中将非指定类型作为参数传递的最佳方法?
- Qt - QVector 和模型视图 - 从列表视图获取自定义类的最佳方法是什么?
- 使用 Git 处理 C++ Visual Studio 2019 解决方案的外部依赖项源代码管理的最佳方法是什么?
- 比较两个节点坐标的最佳方法是什么?
- 在nodejs中使用本机代码的最佳方法是什么?
- 将 pybind11 绑定标记为已弃用的最佳方法
- C++:将向量传递到构造函数以创建成员变量的最佳方法?
- C++中变量混叠的最佳方法
- 读取大文件(>2GB)(文本文件包含以太网数据)并通过不同参数随机访问数据的最佳方法是什么?