static const对象不保留值

时间:2013-10-29 22:49:08

标签: c++ function c++11 int return

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

以下是重要部分:

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。我不知道为什么会这样做,但我认为这可能与我宣布所有Block为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的全部内容。

3 个答案:

答案 0 :(得分:1)

问题是idMap构造函数放置在nameMapBlock(string,uint16,uint8)中的对象是正在构造的对象的副本 - 在_tex初始化之前。

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

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

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

答案 1 :(得分:1)

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

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

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

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

答案 2 :(得分:0)

你有点不清楚你真正想要做什么,因为你没有在这里发布你的代码中足够但至关重要的部分(特别是Block类的声明)。

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