我正在制作类似于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);
答案 0 :(得分:1)
问题是idMap
构造函数放置在nameMap
和Block(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中。但如果是这样,我不相信你的示例代码会按原样编译。