我正在考虑为我的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
}
}
在我看来,第二个“解决方案”在代码方面看起来更清晰,但第一个更容易使用;我可以让方法保持静态,所以我不必担心去耦。
我真的不知道应该从第二种方法中把管理者的实例放在哪里。可能我会将实例设置为静态并将它们放在我的主类中,但这似乎不对。
答案 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));
}
这有点脏,而且根本不安全,它可能会破坏,但它可以像你期望的那样工作。你的第二种方法可能是最好的: - )