Глобальный доступ к данным синглтона

Итак, я делаю графическое приложение (игру), в котором хочу использовать Asset Manager. Для этого класса я решил использовать Singleton Design. Итак, в моем main.cpp я бы загрузил что-то вроде...

ASSET_MANAGER.LoadImage("res/graphics/background.png", "background");

Вот значение макросов/методов, использованных в строке выше. Это своего рода мэшап кода, который мне нужно упростить, вместо того чтобы вставлять сюда несколько сотен строк кода.

активменеджер.h

#define ASSET_MANAGER AssetManager::GetAssetManager()
#define DEBUG

class AssetManager {
public:
static AssetManager &GetAssetManager();

//-----------------------------------------------------------------------------
// Purpose: Load a new image for the game to use. This function will store an
//          instance of the asset in memory (in a hash map corresponding with
//          the data type provided.
//
// param file: The location on disk of the asset
// param key: The string you use to receive this asset (defaults to the path str)
//-----------------------------------------------------------------------------
bool LoadImage(const char *file, const char *key = "");

//-----------------------------------------------------------------------------
// Purpose: Returns the image
//
// param key: The string used to store the asset in memory
//-----------------------------------------------------------------------------
ALLEGRO_BITMAP *GetImage(const char *key);

//-----------------------------------------------------------------------------
// Purpose: Destroys an asset that is presumably no longer needed by the game.
//          This function is good for performance so that you don't use more
//          RAM than you need to.
//
// param key: The string you use to receive this asset (defaults to the path str)
//-----------------------------------------------------------------------------
void DiscardImage(const char *key);
private:
    AssetManager();

    ~AssetManager();

    std::map<const char *, std::shared_ptr<ALLEGRO_BITMAP>> _ImageMap;
}

assetsmanager.cpp

AssetManager &AssetManager::GetAssetManager() {
    static AssetManager instance;
    return instance;
}

bool AssetManager::LoadImage(const char *file, const char *key) {
    key = key == "" ? file : key;
    std::shared_ptr<ALLEGRO_BITMAP> x(al_load_bitmap(file), al_destroy_bitmap);
    if (!x) {
        fprintf(stderr, "Failed to load %s\n", file);
        return false;
    }
#ifdef DEBUG
    printf("DEBUG: Loaded %s\n", key); //debug
#endif // DEBUG
    _ImageMap.insert(std::pair<const char *, std::shared_ptr<ALLEGRO_BITMAP>>(key, x));
    return true;
}

ALLEGRO_BITMAP *AssetManager::GetImage(const char *key) {
    return _ImageMap.find(key) != _ImageMap.end() ? _ImageMap.at(key).get() : nullptr;
}

void AssetManager::DiscardImage(const char *key) {
    _ImageMap.erase(key);
#ifdef DEBUG
    printf("DEBUG: Discarded %s\n", key); //debug
#endif // DEBUG
}

Этот класс работает только из класса, в котором я инициализировал менеджер активов, в то время как я ожидал, что он будет работать везде, где я назвал ASSET_MANAGER. Он компилируется нормально, он падает только тогда, когда я пытаюсь использовать менеджер в другом классе и передать его в функцию аллегро, потому что он возвращает что-то, что равно нулю, вместо правильных типов данных аллегро. Что я не понимаю в этом?


person Thomas Steinholz    schedule 01.03.2016    source источник
comment
Возможно, вы могли бы объяснить, почему это не работает в других местах? Не компилируется? Это крах? Он загружает только котят?   -  person molbdnilo    schedule 01.03.2016
comment
С другой стороны, если вы не используете исключительно строковые литералы и не будете осторожны, const char* в качестве ключа карты в основном бесполезен, поскольку вы отображаете указатели, а не строки. Предпочитаю std::string.   -  person molbdnilo    schedule 01.03.2016
comment
+molbdnilo Компилируется нормально, но в классах, где ASSET_MANAGER не был определен, не получает данные. Функция GetImage() просто возвращает значение null вместо данных, которые я загрузил. Это приводит к сбою приложения allegro, поскольку оно не может отображать значение null.   -  person Thomas Steinholz    schedule 01.03.2016
comment
Это почти наверняка потому, что вы сопоставляете указатели.   -  person molbdnilo    schedule 01.03.2016
comment
+molbdnilo Значит на картах не должно быть указателей? В чем проблема с этим?   -  person Thomas Steinholz    schedule 01.03.2016
comment
Проблема в том, что вы используете расположение строки в качестве ключа, а не ее содержимое. Например, если вы LoadImage("foo"...), то char[] foo = "foo"; ... GetImage(foo, ...) потерпит неудачу.   -  person molbdnilo    schedule 01.03.2016
comment
Другая проблема заключается в том, что по умолчанию key равно "", что правда. Таким образом, вы сохраняете все, используя один и тот же ключ (то есть указатель на пустую строку), если вы не укажете его.   -  person molbdnilo    schedule 01.03.2016
comment
будет полезно, если вы опубликуете код, вызывающий сбой.   -  person Lidong Guo    schedule 01.03.2016
comment
Ключ по умолчанию — это имя файла, но я попробую изменить const char* на std::string.   -  person Thomas Steinholz    schedule 01.03.2016
comment
+ Лидун Го, авария из аллегро говорит, что активы, которые я пытаюсь использовать, пусты.   -  person Thomas Steinholz    schedule 01.03.2016
comment
+molbdnilo, вы должны опубликовать, если вы не используете исключительно строковые литералы и не будете осторожны, const char* в качестве ключа карты в основном бесполезен, поскольку вы сопоставляете указатели, а не строки. Предпочитаю std::string в качестве ответа, чтобы я мог нажать кнопку с галочкой.   -  person Thomas Steinholz    schedule 01.03.2016


Ответы (1)


Char* на карте хранит местоположение, а не данные, из-за чего программа считает, что оно пустое.

person Thomas Steinholz    schedule 09.03.2016