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

Using C++ templating for SFML Resource Manager

本文关键字:C++ 模板 SFML 资源管理器      更新时间:2023-10-16

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

我想做这样的事情:

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
    }
}

在我看来,第二个"解决方案"在代码方面看起来更干净,但第一个会更容易使用;我可以将方法设为静态,这样我就不必担心解耦。

真的不知道我应该把第二种方法中的经理实例放在哪里。也许我会使实例静态并将它们放在我的主类中,但这似乎不对。

虽然很好,但它会变得非常混乱,因为您不能在同一张地图中使用不同的资源类型。它们没有公共基类。不过,您没有那么多不同的资源,所以我建议您将它们拼写出来。

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

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;
};

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

如果要使用第一种方法,可以做的是存储void*指针(其大小已知),然后让函数将此指针转换为右侧指针类型。

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

这有点脏,根本不安全,它可能会损坏,但它可以按您的预期工作。您的第二种方法可能是最好的:-)