0

我正在制作一个类似于 Minecraft 的游戏,其中所有不同的块都由static const Block <name>;.h 文件中的单个块表示。我在 .cpp 文件中将它们初始化为const Block Block::<name> = Block("name", 0, 0);,并在构造函数中传入它使用的纹理的索引(表示为无符号字符)。在构造函数中,它设置了索引变量,但是当我稍后在程序中尝试调用它时,它返回一个完全不同的值。

以下是重要部分:

Block::Block(std::string name, uint16 id, uint8 tex)
{
    //Check for repeat ids
    if (IdInUse(id))
    {
        fprintf(stderr, "Block id %u is already in use!", (uint32)id);
        throw std::runtime_error("You cannot reuse block ids!");
    }
    _id = id;
    idMap.insert(std::make_pair(id, *this));
    //Check for repeat names
    if (NameInUse(name))
    {
        fprintf(stderr, "Block name %s is already in use!", name);
        throw std::runtime_error("You cannot reuse block names!");
    }
    _name = name;
    nameMap.insert(std::make_pair(name, *this));

    _tex = tex;
    fprintf(stdout, "Using texture %u\n", _tex);

    _transparent = false;
}

uint8 Block::GetIndex() const
{
    fprintf(stdout, "Returning texture %u\n", _tex);
    return _tex;
}

我将 0 作为 传递给构造函数tex,并_tex在分配打印出 0 后打印,所以我知道它在构造函数中正确设置。但是,当程序GetIndex()稍后调用时,由于某种原因,它总是返回 204。我不知道它为什么这样做,但我认为这可能与我声明所有 Blocks 为static const. 另外,我知道 _tex 的值没有改变,因为对象是const并且 Block 在初始化后没有以任何方式进行操作。

如果有人知道可能导致这种情况的原因,我们将不胜感激任何帮助。

编辑:

在 Block.h 中,这是声明块的行,取自内部class Block

public:
    static const Block Test;

然后在 Block.cpp 中,这是文件顶部的一行:

const Block Block::Test = Block("Test", 1, 0);

这是block.hblock.cpp的全部内容。

4

3 回答 3

1

idMap的定义我看不出来,但是很清楚std::map<uint16, Block>。这意味着它包含您的 Block 的副本。当您将构造推送到地图中时,它会通过调用复制构造函数来创建一个新块->idMap.insert(std::make_pair(id, *this));

请注意,这发生在您设置 _tex 变量之前,因此新副本具有随机 _tex 值。

您不应将指针传递给 Block。当 Block 超出范围并被清理时,这将导致分段错误。

您应该真正了解并使用 boost::flyweight ,这是您在此处尝试使用的模式

于 2013-10-30T07:06:19.227 回答
1

问题是构造函数放置idMap的对象nameMapBlock(string,uint16,uint8)构造对象的副本 - before_tex被初始化。

请注意,同样的问题适用于_name成员(至少对于idMap集合)和_transparent成员。

因此,当您从其中一个集合中查找对象时,您会检索到不完美的副本。

在将对象添加到集合之前,您应该完全构造它。让地图存储指向对象的指针而不是副本也可能更有意义。如果您不打算复制这些Block对象,您还应该禁用复制和赋值构造函数。

于 2013-10-30T06:49:15.997 回答
0

有点不清楚您实际上要做什么,因为您没有在此处发布足够但至关重要的代码部分(Block特别是类的声明)。

您的声明static const Block <name>;似乎暗示了一个模板声明,其中静态成员实例需要在模板头中定义,而不是在单独的 .cpp 中。但如果是这样,我不相信您的示例代码会“按原样”编译。

于 2013-10-30T00:46:43.333 回答