Несколько определений статической переменной шаблонного класса - PullRequest
1 голос
/ 31 января 2012

У меня есть шаблонный класс с именем PooledResource.Он обрабатывает для меня такие вещи, как текстуры и звуки, и гарантирует, что я не загружу один и тот же несколько раз при аварии.Ресурсы определенного типа всегда будут находиться в определенном подкаталоге, и я хотел упростить их загрузку, поэтому я решил добавить статическую переменную, которая отслеживает корневую папку для определенного типа ресурса.

template <typename T>
class PooledResource
{
public:
    // ...

    static const char* PathPrefix;
    static ResourceTable myResourceTable;


    static void load(const char* filename)
    {
        // Any attempt to use PathPrefix in here causes a compilation error
        // All I want to do is use PathPrefix and filename to get the full
        // path do a file and load it. 
    }
};

template <typename T>
const char* PooledResource<T>::PathPrefix = NULL;

template <typename T>
typename PooledResource<T>::ResourceTable PooledResource<T>::myResourceTable;

Идея состоит в том, что я могу использовать версию этого типа для различных типов.Например, в PooledTexture.hpp у меня будет:

typedef PooledResource<Texture> PooledTexture;

, а в PooledTexture.cpp у меня будет:

template <>
const char* PooledTexture::PathPrefix = "../assets/textures/";

Это все скомпилируется и будет работать нормально, если я этого не сделаюпопытайтесь использовать PathPrefix в функции загрузки выше.Однако, как только я его использую, я получаю такие ошибки:

 90 || CMakeFiles/game.dir/PooledTexture.cpp.o:(.data+0x0): multiple definition of `ag::PooledResource<sf::Texture>::PathPrefix'
 91 CMakeFiles/game.dir/lua/LuaFrame.cpp.o:/usr/include/c++/4.6/i686-linux-gnu/./bits/gthr-default.h|241| first defined here

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

1 Ответ

6 голосов
/ 31 января 2012

Проблема здесь в том, что ваше пространство для переменной выделяется в заголовке, который затем включается несколькими блоками компиляции - LuaFrame.cpp.o и PooledTexture.cpp.o. Примечание: присвоение имен вашим объектным файлам .cpp.o сбивает с толку.

Итак, есть две переменные с одинаковым именем.

Вам нужно переместить фактическое выделение места (не объявление, а бит, в котором вы его назначаете) в файл cpp вместо заголовка, а затем встроить этот файл вместе с остальной частью вашего приложения. Да, теперь у вас есть заголовок: бит, в котором вы установили NULL!

РЕДАКТИРОВАТЬ: когда вы делаете это, в заголовке больше не будет достаточно информации для создания экземпляра шаблона, поэтому вам придется явно создавать экземпляр класса для каждого типа, с которым вы хотите его использовать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...