包装 API 时,我是否应该避免在实现类中进行向上转换

Should I avoid upcasting in implementation classes when wrapping an API

本文关键字:实现 转换 API 是否 包装      更新时间:2023-10-16

我正在编写一些 c++ 代码,并希望将 SFML 用于我的 GUI 实现。我尝试编写一个纯虚拟 GUI 类以及一些相关类,例如用于绘制的 Surface,而不是公开内部类型。然后,我在 SFML 中为每个实现。我的问题是GUI的draw(Surface s)函数需要访问SFML类型sf::Texture,我需要从我的Surface对象访问该类型。

现在,我知道我的代码中的任何 Surface 都将使用与 GUI 类相同的 API,因为我只有一个实现。我正在尝试编写好的代码,因为这主要是一个学习练习,我相信这将打破 Liskov 替换原则。

试图在下面尽可能简单的代码中概述我的问题:

class Surface {
  // ...
};

class SFML_Surface : public Surface {
public:
  sf::Texture* get_texture() {
    return _surface->getTexture();
  }
  // ...
private:
  sf::RenderTexture* _surface;
};

class GUI {
public:
  virtual void render(Surface *s) = 0;
  // ...
};

class SFML_GUI : public GUI {
public:
  void render(Surface *s) {
    SFML_Surface *surface = static_cast<SFML_Surface*>(s);
    if(surface == 0)
      return;
    this->_window->render(surface->getTexture());
  }
};

我对从这里开始有点茫然,我想不出一种明显的方法来解决类间依赖关系,而无需在某些部分进行投射。

我将不胜感激对上述代码的任何想法,或对替代方法的讨论。或者,正如标题所问的那样,在这种特定情况下,抛弃是一个坏主意吗?

提前谢谢。

代码编辑:dynamic_cast应该是一个static_cast

class Surface {
  // ...
  virtual TextureBase* get_texture() = 0; 
};

class SFML_Surface : public Surface {
public:
   sf::Texture* get_texture() {   // define sf::Texture to inherit from Texture Base
     return _surface->getTexture();
}
// ...
private:
   sf::RenderTexture* _surface;
};

这个想法是返回类型不需要相同,只要它与原始返回类型共变即可。