C ++基于ID识别类

时间:2011-08-10 18:50:08

标签: c++

好的,所以我正在制作一个基于图块的游戏,我正在从一个文件中加载一个世界。所以我得到一个大约100 x 15个字符的数组,每个字符代表一个磁贴的ID。假设我有32种类型的瓷砖,每种瓷砖都有特殊属性。它们都从Tile类继承,每个都有一个ID 0-31。我想创建一个100 x 15个瓷砖的Tile数组,另一个带有chars的数组会告诉我哪些瓷砖放在哪里。但基本上,我怎样才能最有效地找出ID属于哪个区块?

说,我只读了一个字符,它是3,与某些图块“D”相关。 那么,我应该做这种类型的事情:

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

这对我来说似乎很慢,不得不这么做。就像我在一个级别中有1000个tile,以及255个类型的tile一样,这是255000个检查来加载该级别。我希望某种类似于Tile类的数组。如:

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

依旧......

那样,我可以打电话:

(tileClassArray[IDFromChar])(parameters)

作为构造函数,无需遍历每个Tile类。但我不知道如何制作一个类数组,或者如果可能的话。

你得到我想说的话吗?任何帮助都会很好。

5 个答案:

答案 0 :(得分:3)

可悲的是,你无法存储构造函数。你必须创建一个模板函数来创建一个对象,然后存储指针,然后你可以通过索引调用该函数。

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])();

但是,我无法想到一种方法,在键入方面效率不会O(n):)

答案 1 :(得分:2)

那不是真的。 switch语句可能会被编译为O(1)跳转表。此外,一旦你得到大量的数量的tile,你应该认真考虑根据函数的变化转移到分支 - 即继承,函数对象(包括函数指针)。

答案 2 :(得分:1)

听起来你想要一张地图,它可以很好地使用std::unordered_mapstd::map。由于您提到每个类都将从父Tile类继承,因此您可以将地图类型设置为类似

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

现在,您将通过基本循环索引并创建在堆上分配的Tiles来设置地图,以便您可以在地图中放置从Tile派生的切片。例如:

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

访问地图的元素将通过int类型的键值完成,并且将像普通的数组语法一样完成,除了返回值是指向具有节点的节点的交互器数据元素类型std::shared_ptr<Tile>。取消引用迭代器后,shared_ptr可以使用正常的指针退出语法进行操作。

如果需要根据某些条件创建新对象,最好的方法是查看一个基于switch语句的工厂函数,并返回指向正确派生类型的指针。然后,在为std::map创建对象时,您将调用工厂函数。

答案 3 :(得分:0)

您可以像创建任何其他数组一样创建类数组。

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

在一个级别中只有~1000个瓷砖,您最好的选择可能就是将瓷砖存储在如上所示的阵列中。只要级别大小不经常改变,这应该没问题。

我会存储的类是Tile类型。对于每种类型的图块,使用该图块的属性创建一个derrived类。 inheritance

答案 4 :(得分:0)

C ++的反射功能非常有限,所以你所指的并不是直接可能的。即便如此,如果可能的话,开销可能会使其效率远低于switch语句。

如果性能是您的目标,那么switch语句将是您最好的选择。每种情况都在大多数机器语言中实现为单个跳转语句,因此您的255,000个检查可能对应于255,000个指令,大多数现代处理器可以在不到1毫秒的时间内执行。

编辑:请参阅DeadMG的答案,关于跳转表。那个switch语句可能比我描述的更有效。