C ++:Making方法每次都返回相同的对象

时间:2011-01-04 00:03:24

标签: c++ opengl static static-methods

我想有一个加载文件的函数(在这种情况下是一个OpenGL纹理),但实际上只加载一次文件,每次调用它之后它只返回它最初加载的文件。

这样做的好方法是什么?

感谢。

6 个答案:

答案 0 :(得分:6)

您需要一些地方来存储该州。它既可以在对象内部,也可以作为静态变量。让我们说:

class TextureLoader {
public:
    TextureLoader() {}
    GLuint loadTexture(std::string const & filename){
        std::map<std::string, GLuint>::iterator it = m_loadedTextures.find(filename);
        if(it == m_loadedTextures.end()){
            GLuint id = load(filename);
            m_loadedTextures[filename] = id;
            return id;
        }
        else{
            return it->second;
        }
    }
    ~TextureLoader(){
        // iterate and delete textures
    }
private:
    GLuint load(std::string const & filename){
        // real loading
    }
    std::map<std::string, GLuint> m_loadedTextures;
};

答案 1 :(得分:4)

执行此操作的一种方法是在函数内部使用静态映射,该函数将参数与函数(此处为文件名)相关联,并指向其返回的唯一值。然后,您可以使用该函数检查地图是否包含输入,如果是,则返回与其关联的纹理。否则,您可以执行加载,将结果存储在地图中,然后交回结果。例如:

Texture* LoadTexture(const std::string& filename) {
    static std::map<std::string, Texture*> previousResults;

    /* Look up existing value. */
    Texture* result = previousResults[filename];

    /* If this doesn't exist, then go create it and pretend it was there all along. */
    if (result == NULL)
        result = previousResults[filename] = ActuallyLoadTexture(filename);

    /* Hand back the cached result. */
    return result;
}

如果这样做,您应该注意线程安全性,因为多次调用该函数可能会导致映射问题。适当地进行Syncrhonize。

答案 2 :(得分:2)

听起来你正在寻找的是Singleton设计模式的实现。

有多种方法可以实现这一点,现在您知道它的名称,您可以决定哪种方法最好。对于其他类似的问题,您的第一站可能是本网站的search

答案 3 :(得分:2)

通常,您可以将地图或unordered_map文件路径与Texture *相关联。

class render_state {
    std::map<std::string, Texture> textures;
    Texture* load_texture(std::string filepath) {
        if (textures.find(filepath) != textures.end()) {
            return &textures[filepath];
        }
        // load the texture here if it's not in cache
    }
    // Other rendering methods and state here.
};

但是现在,您还有另一个问题,即有时您可能会使用相对文件路径,有时甚至是绝对文件路径。此外,在某些库中,它们可以接受不同版本的换行符和反斜杠或正斜杠。如果我加载了纹理,然后仅在特定时间使用它并且不再需要它怎么办?哎呀,内存泄漏。

最好的办法就是返回一个Texture对象(或者(可能是智能的)指针)并让用户担心管理它。如果有人创建了资源,则他们的作业来管理它,而不是你的。

答案 4 :(得分:0)

boost::flyweight。它几乎可以满足您的需求。加载对象避免重复。

答案 5 :(得分:0)

这是你想要的:

Texture& loadTexture(cosnt std::string& texture)
{
    // Store all loaded data here
    // Each file maps to a loded texture object
    static boost::ptr_map<std::string, Texture>   data;

    boost::ptr_map<std::string, Texture>::iterator find = data.find(texture);
    if (find == data.end())
    {
        // If it is not in the structure then load it this one time
        find = data.insert(texture, doLoad(texture));
    }

    // return a reference to the texture
    return *(find->second);
}