sm81095
sm81095

Reputation: 300

static const objects are not retaining values

I am making a game similar to that of Minecraft, where all of the various blocks are represented by a single static const Block <name>; in the .h file. I initialize them in the .cpp file as const Block Block::<name> = Block("name", 0, 0);, and in the constructor I pass in the index of the texture it uses (represented as an unsigned char). In the constructor, it sets the index variable, but when I try to call it later in the program, it returns an entirely different value.

Here are the important parts:

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;
}

I am passing 0 into the constructor as tex, and printing _tex after the assignment prints out 0, so I know that it is getting set properly in the constructor. However, when the program calls GetIndex() later on, it always returns 204 for some reason. I do not know why it is doing this, but I think it may have something to do with the fact I declare all of the Blocks to be static const. Also, I know that the value of _tex is not getting changed because the object is const and the Block is not manipulated in any fashion after being initialized.

If anyone knows what might be causing this, any help is greatly appreciated.

EDIT:

In Block.h, this is the line that declares the blocks, taken from within class Block:

public:
    static const Block Test;

And then in Block.cpp, this is a line towards the top of the file:

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

Here is the entirety of block.h, and block.cpp.

Upvotes: 0

Views: 161

Answers (3)

odedsh
odedsh

Reputation: 2624

I can't see the definition of idMap, but it is quite clearly std::map<uint16, Block>. This means it contains copies of your Block. When you push your construct into the map it creates a new Block by calling the copy constructor-> idMap.insert(std::make_pair(id, *this));

Notice that this occurs before you set the _tex variable so the new copy has a random _tex value.

You should not pass a pointer to the Block. This will cause a segementation fault the moment Block gets out of scope and is cleaned.

You should really get to know and use boost::flyweight which is the pattern you are trying to use here

Upvotes: 1

Michael Burr
Michael Burr

Reputation: 340188

The problem is that the objects being placed inidMap and nameMap by the Block(string,uint16,uint8) constructor are copies of the object being constructed - before _tex is initialized.

Note that the same problem applies to the _name member (at least for the idMap collection) and the _transparent member.

So when you look up an object from one of those collections, you retrieve an imperfect copy.

You should fully construct the object before adding it to a collection. It might also make more sense to have the maps store a pointer to the object rather than a copy. You should also disable the copy and assignment constructors if you don't intend for these Block objects to be copied.

Upvotes: 1

πάντα ῥεῖ
πάντα ῥεῖ

Reputation: 1

It's a bit unclear what you're actually trying to do, since you don't post sufficient but crucial parts of your code here (the declaration of the Block class in particular).

Your statement static const Block <name>; seems to imply a template declaration where static member instances need to be defined in the template header, and not in a separate .cpp. But if so, I don't believe that your sample code would compile 'as is'.

Upvotes: 0

Related Questions