模板类的静态变量的多个定义

发布于 2025-01-01 02:40:08 字数 1512 浏览 1 评论 0原文

我有一个名为 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;

我的想法是,我可以将其 typedef 版本用于各种类型。例如,在 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

我尝试用一​​个更简单的案例来重现这个问题,以试图找出问题,但我尝试的其他案例似乎有效。我不确定我在这里所做的不同操作会导致此错误。

I have a templated class called PooledResource. It handles loading things like textures and sounds for me and ensures that I don't load the same one multiple times on accident. Resources of a certain type will always be in a certain subdirectory, and I wanted to make it easier to load them, so I decided to add a static variable that keeps track of the root folder for a certain type of resource.

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;

The idea is that I can use a typedef'd version of this for various types. For example, in PooledTexture.hpp I would have:

typedef PooledResource<Texture> PooledTexture;

and in PooledTexture.cpp I would have:

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

This will all compile and run fine if I don't attempt to use PathPrefix in the load function above. As soon as I use it though, I get errors like this:

 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

I've tried reproducing this with a simpler case to try to hunt down the problem, but other cases I try seem to work. I'm not sure what I'm doing differently here that would cause this error.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

安静被遗忘 2025-01-08 02:40:08

这里的问题是变量的空间是在标头中分配的,然后由多个编译单元包含 - LuaFrame.cpp.oPooledTexture.cpp.o 。旁注:命名您的目标文件 .cpp.o 很容易混淆。

因此,有两个同名的变量。

您需要将实际的空间分配(不是声明,而是分配它的位)移动到 cpp 文件而不是标头中,然后将该文件与应用程序的其余部分一起构建。是的,您现在已将其放在标头中:将其设置为 NULL 的位!

编辑:当您执行此操作时,标头将不再有足够的信息来创建模板的实例,因此您必须为您希望使用它的每种类型显式实例化该类。

The problem here is that your space for the variable is allocated in the header, which is then included by multiple compilation units - LuaFrame.cpp.o and PooledTexture.cpp.o. Side note: naming your object files .cpp.o is confusing.

So, there are two variables with the same name.

You need to move the actual space allocation (not the declaration, but the bit where you assign it) into a cpp file instead of a header, and then build that file in with the rest of your application. Yes, you have it in a header now: the bit where you set it to NULL!

EDIT: when you do this, the header will no longer have enough information to create an instance of the template, so you'll have to explicitly instantiate the class for each type with which you wish to use it.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文