关于c ++:SFML实现draw函数时派生类的模棱两可转换

SFML Ambiguous conversion from derived class when implementing draw function

我正在尝试通过自己的游戏引擎创建游戏,其中每个基本引擎都是一个GameObject,它将由一个更新功能和其他通知程序组成。

到目前为止,这是我的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#include <SFML/Audio.hpp>
#include <SFML/Graphics.hpp>
#include"AssetManager.hpp"

class GameObject : public sf::Drawable, public sf::Transformable
{
public:
  virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const{
    target.draw(*this, states);
  };
};

class Sprite : public GameObject, public sf::Sprite {
public:
  Sprite(AssetManager assetManager, std::string assetName) : sf::Sprite(){
    setTexture(assetManager.getTextureNamed(assetName));
  }
};


int main(int argc, char const** argv)
{
  sf::RenderWindow window(sf::VideoMode::getDesktopMode(),"");
  AssetManager assetManager = AssetManager("/Users/iProgram/Desktop/My Game Engine/My Game Engine");
  assetManager.loadTextureWithName("tank","tank.png", sf::Vector2f(16,16));

  Sprite tank = Sprite(assetManager,"tank");

  while(window.isOpen()){
    window.clear();
    window.draw(tank);
    window.display();
  }

  return EXIT_SUCCESS;
}

请注意,资产管理器仅将纹理存储在内存中,并在需要时以给定大小返回纹理。

问题出在线上:window.draw(tank);,我得到了错误

Ambiguous conversion from derived class 'const Sprite' to base class 'const sf::Drawable':

为什么在我已经在GameObject类中实现了draw函数的情况下,该如何解决?


您的Sprite类从GameObject继承,而GameObjectsf::Drawable继承。 您的类还从sf::Sprite继承,而sf::Sprite也从sf::Drawable继承。 现在,您的Sprite类具有2个继承的sf::Drawable子对象,并且编译器无法选择。

要解决此问题,请重新考虑您的设计或虚拟继承。


为了解决这个问题,我不必像某些建议那样使用私有继承,我只需要我的基类(GameObject)就什么都不继承。 然后,我的Sprite类将继承sf::Sprite,如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#include <SFML/Audio.hpp>
#include <SFML/Graphics.hpp>
#include"AssetManager.hpp"

class GameObject{
public:
  virtual void update(){}
};

class Sprite : public GameObject, public sf::Sprite {
public:
  Sprite(AssetManager* assetManager, std::string assetName) : sf::Sprite(assetManager->getTextureNamed(assetName)){
  }
};

class Tank: public Sprite{
public:
  Tank(AssetManager* assetManager) : Sprite(assetManager,"tank"){
    setScale(3, 3);
  };

  virtual void update(){
    move(1,0);
  }
};

int main(int argc, char const** argv)
{
  sf::RenderWindow window(sf::VideoMode::getDesktopMode(),"");
  AssetManager* assetManager = new AssetManager("/Users/iProgram/Desktop/My Game Engine/My Game Engine");
  assetManager->loadTextureWithName("tank","tank.png", sf::Vector2f(16,16));

  Tank tank = Tank(assetManager);
  while(window.isOpen()){
    sf::Event event;
    while(window.pollEvent(event)){
      if(event.type == sf::Event::Closed){
        window.close();
      }
    }
    tank.update();
    window.clear();
    window.draw(tank);
    window.display();
  }

  return EXIT_SUCCESS;
}