开发者

C++ Identifying Classes based on an ID

Okay, so I'm making a tile-based game, and I am loading a world from a file. So I get an array of about 100 x 15 chars, with each char representing the ID of a tile. Say I have 32 开发者_Python百科types of tiles, each with special properties. They all inherit from a Tile class, and they each have an ID 0-31. I want to create a Tile array of 100 x 15 tiles, and the other array with the chars will tell me which tiles to put where. But basically, how can I most efficiently figure out which tile the ID belongs to?

Say, I just read a char and it is 3, which correlates to some tile "D". So, should I do this type thing:

switch(idFromChar)
case 0: tile A
case 1: tile B
case 2: tile C
case 3: tile D

That seems slow to me though, having to do that potentially a lot. Like if I have 1000 tile in a level, and 255 types of tiles, that's 255000 checks to load the level. I was hoping for something like somehow an array, of Tile classes. As in:

tileClassArray[0] = A
tileClassArray[1] = B

and so on...

That way, I could just call:

(tileClassArray[IDFromChar])(parameters)

as a constructor, without having to loop through each Tile class. But I don't know how to make an array of classes, or if it is possible.

Do you get what I'm trying to say? Any help would be nice.


Sadly, you can't store constructors. You'll have to make a template function to create an object, then store pointers to that, then you can call that function through the index.

class Tile { ... }; // base class
class TileA : public Tile { ... };
class TileB : public Tile { ... };
class TileC : public Tile { ... };
...

template<typename T>
Tile* createTile() {
    return new T;
};

typedef Tile*(*TileCreator)();

TileCreator creationFuncs[] = {
    &createTile<TileA>,
    &createTile<TileB>,
    &createTile<TileC>,
    ....
};

Tile* newTile = (creationFuncs[type])();

However, I can't think of a way to do this that won't be O(n) efficiency with regards to typing :)


That's not true. The switch statement will likely be compiled down to an O(1) jump table. Besides, once you get to large numbers of tiles, you should seriously consider moving to branching based on function changes- i.e., inheritance, function objects (including function pointers).


Sounds like you want a map, which would work nicely using either std::unordered_map or std::map. Since you mentioned that each class would inherit from a parent Tile class, you could set the type of the map to something like

std::map<int, std::shared_ptr<Tile> > tile_map;

Now you would setup the map by basically cycling through your indexes, and creating Tiles allocated on the heap, so that you could put tiles that are derived from Tile in your map. For instance:

tile_map[0] = new Derived_Tile_A();
tile_map[1] = new Derived_Tile_B();
//... keep adding to map

Accessing the elements of the map would be done through the int type key-values, and would be done like a normal array-syntax, except that the return value would be an interator pointing to a node with a data-element type of std::shared_ptr<Tile>. Once you dereference the iterator, the shared_ptr can be operated on with normal pointer defererencing syntax.

If you need to create a new object based on some condition, the best thing would be to look into a factory function that would be based on a switch statement and return a pointer to the proper derived type. You would then call the factory function when creating your objects for the std::map.


C++ has very limited reflection capabilities, so what you're referring to is not directly possible. Even so, if it were possible, the overhead would likely make it far less efficient than a switch statement.

The switch statement is going to be your best bet if performance is your goal. Each case is implemented as a single jump statement in most machine languages, so your 255,000 checks will likely correspond to 255,000 instructions, which most modern processors can execute in less than 1ms.

Edit: See DeadMG's answer too, about jump tables. That switch statement will probably be even more efficient than I described.


You make an array of classes just as you would make any other array.

Tile tileClassArray[255];//makes an array of type classname with 255 members

With only ~1000 tiles in a level your best bet might be to just store the tiles in a array like the one above. This should be fine as long as the level size doesn't change often.

The class I would store would be say, of type Tile. For each type of tile make a derrived class with the properties of that tile. inheritance

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜