将结构实例存储在std :: map中

sha*_*vey 5 c++ templates struct stl

我正在尝试将一些结构映射到其他一些实例,如下所示:

template <typename T>
class Component {
public:

    typedef std::map<EntityID, T> instances_map;

    instances_map instances;

    Component() {};

    T add(EntityID id) {
        T* t = new T();
        instances[id] = *t;
        return *t;
    };  
};
Run Code Online (Sandbox Code Playgroud)

然后我像这样使用它:

struct UnitInfos {
    int owner_id;
    int health;
    float x, y;
};

class LogicComponent : public Component<UnitInfos> {};
Run Code Online (Sandbox Code Playgroud)

问题是,以后稍后检索数据时,如下所示:

comp.instance[id];
Run Code Online (Sandbox Code Playgroud)

我得到一个breand新对象,其属性初始化为默认值.

这段代码是否存在内在错误,或者我是否遗漏了有关该问题的信息?


根据@aaa建议,我将代码更改为

typedef std::map<EntityID, T> instances_map;
instances_map instances;
T& add(EntityID id) {
    instances[id] = T();
    return instances[id];
};
Run Code Online (Sandbox Code Playgroud)

但当我访问它

UnitInfos &info = logic_c.instances[id];
Run Code Online (Sandbox Code Playgroud)

info.x的值仍为0.任何指针?


问题是我如何在另一个类中存储对LogicComponent的引用.使用LogicComponent logic_c;而不是LogicComponent& logic_c;.它现在有效,但我在地图中存储指针(而不是@aaa的建议).这是一个坏主意吗?

car*_*org 4

明确您要在 LogicComponent 上执行的操作。假设您正在尝试实现这样的目标:

第 1 步:向地图添加新条目:

LogicComponent comp; 
EntityID id = 99;
UnitInfos info = comp.add(id);
Run Code Online (Sandbox Code Playgroud)

第二步:初始化信息:

info.x = 10.0;
info.y = 11.0
// etc
Run Code Online (Sandbox Code Playgroud)

第三步:再次获取info对象:

UnitInfos info2 = comp.instances[id]; // this is uninitialized.
Run Code Online (Sandbox Code Playgroud)

然后,按顺序添加一些代码注释:

comp.add 返回的信息对象是您添加到地图中的对象的副本。通过修改它,您并没有修改地图中的内容。

最简单的解决方法是创建指向对象的指针映射,而不是对象本身。

typedef std::map<EntityID, T*> pinstances_map;

T * add(EntityID id) {
    T* t = new T();
    instances[id] = t;
    return t;
};  

// initialize as 
UnitInfo *info = comp.add(id);
info->x = 10.0;
info->y = 11.0;

// retrieve as 
UnitInfos *info = comp.instances[id];
Run Code Online (Sandbox Code Playgroud)

另外,请使用访问器方法来获取映射值,而不是将映射对象公开为公共。将实例变量设置为受保护,并添加公共 get() 方法。

编辑:这段代码对我来说效果很好:

#include <map>
#include <iostream>
using namespace std;

template<typename T>
class Component
{
public:
        typedef map<long, T*> pinstances_map;
        pinstances_map instances;

        T * add(long id)
        {
                T *t = new T();
                instances[id] = t;
                return t;
        }
};

struct UnitInfo 
{
        float x, y;
};

class LogicComponent: public Component<UnitInfo> {};

int main()
{
        LogicComponent comp;
        UnitInfo *info = comp.add(99);
        info->x = 10.0;
        info->y = 11.0;

        UnitInfo *info2 = comp.instances[99];
        cout << info2->x << " " << info2->y;

        return 0;
}
Run Code Online (Sandbox Code Playgroud)