为SFML资源管理器使用C ++模板

时间:2014-12-29 23:36:59

标签: c++ templates resources sfml

我正在考虑为我的SFML-Game创建资源管理器的两种解决方案。两者都需要模板化(我是模板化的新手),但我更喜欢其中一种解决方案,即使我真的不知道如何使它成功。

我想做这样的事情:

std::map<string, class> resources;

template<class T> T getResource(std::string name){
    return (T) resources.find(name);
}

换句话说,我希望将所有资源存储在一个类中,并且只有一个函数来获取资源,并且此函数应始终返回资源的类型 - 这样,按顺序加载资源,我可以这样做:

Texture texture = resourceManager.getResource("mytexture.png");

但我无法弄清楚如何让这个工作。

我的第二种方法是模板化一个类,然后实例化多个资源管理器,每种类型的资源一个。

template<class Res> class ResourceManager {
    std::map<string, Res> resources;
    ...
    Res get(std::string name){
        return resources.find(name); //Just to visualize. Of course there would be null checks etc in the real method
    }
}

在我看来,第二个“解决方案”在代码方面看起来更清晰,但第一个更容易使用;我可以让方法保持静态,所以我不必担心去耦。

我真的不知道应该从第二种方法中把管理者的实例放在哪里。可能我会将实例设置为静态并将它们放在我的主类中,但这似乎不对。

2 个答案:

答案 0 :(得分:2)

虽然很好,但它会变得非常混乱,因为你不能在同一个地图中拥有不同的资源类型。他们没有共同的基类。你没有那么多不同的资源,所以我建议你拼出来。

就个人而言,我讨厌字符串作为标识符,因为编译器找不到拼写错误,所以我使用枚举:

enum ResourceIdentifier
{
    // TEXTURES
    LoadingScreenBackground,
    FireAnimation,
    SmokeAnimation,
    FloorTile,
    // ...

    // FONTS
    MainFont
};

class ResourceManager
{
private:
    std::map<ResourceIdentifier, std::shared_ptr<sf::Texture>> m_Textures;
    std::map<ResourceIdentifier, std::shared_ptr<sf::Font>> m_Fonts;

public:
    std::shared_ptr<sf::Texture> LoadTexture(ResourceIdentifier id, const sf::String& file);
    std::shared_ptr<sf::Font> LoadFont(ResourceIdentifier id, const sf::String& file);

    std::shared_ptr<sf::Texture> GetTexture(ResourceIdentifier id) const;
    std::shared_ptr<sf::Font> GetFont(ResourceIdentifier id) const;
};

答案 1 :(得分:1)

第一种方法不起作用,因为您必须知道将其存储在容器中的对象的大小。这就是为什么没有class类型的原因。

如果你想使用你的第一种方法,你可以做的是存储void*指针,其大小已知,然后让你的函数将这个指针返回到右指针类型。

std::map<string, void*> resources;

template<class T> T* getResource(std::string name){
    return static_cast<T*>(resources.find(name));
}

这有点脏,而且根本不安全,它可能会破坏,但它可以像你期望的那样工作。你的第二种方法可能是最好的: - )