std :: map如何/在哪里初始化其成员?

时间:2013-11-30 08:31:58

标签: c++ struct constructor sfml stdmap

我想尽可能地尝试用这个问题来表达这个问题,但它确实与我编程的游戏有关。

我有一个有std :: map成员的类:

class Player {
    ...
    private:
        std::map<Action, Command>  mActionBinding;
    ...
}

Action是Player类中的枚举。它包含ActionLeft,例如MoveLeft或MoveRight。 Command是一个包含函数和类别的结构。

struct Command
{
        Command();

        std::function<void(SceneNode&, sf::Time)>        action;
        unsigned int                                     category;
        // SceneNode&                                    node
};

这个系统背后的想法是我可以将一个将操作SceneNode(我游戏中的可绘制对象)的函数绑定到一个SceneNode类别。游戏的update()将迭代我游戏中的所有SceneNodes,并在SceneNode上执行命令,如果该SceneNode的类别与命令中的类别匹配。 (如果这听起来很熟悉,这是SFML的GQE引擎,源代码可以在这里找到:https://github.com/LaurentGomila/SFML-Game-Development-Book

我希望命令比此实现更具体。我希望在SceneNode上执行命令,如果该SceneNode与命令指定的那个匹配,而不仅仅是类别比较。

但是,命令是在此Player类中创建的,它们是在该std :: map中创建的。 Player的构造函数调用initializeAction()函数,该函数调用类似:

mActionBinding[MoveLeft].action = 
      derivedAction<SpaceCraft>(SpaceCraftMover(-playerSpeed, 0.f));

基本上,它将动作设置为操纵航天器节点的某个功能。稍后在Player构造函数中,mActionBinding的命令类别设置如下:

for(auto& pair : mActionBinding)
            pair.second.category = Category::PlayerSpaceCraft;

我的问题:Command的构造函数在我能看到的地方被调用了no。我想更改Command的构造函数以接受SceneNode&amp;所以我可以将它设置为SpaceCraft节点(用注释的SceneNode&amp;替换unsigned int)。如何以可以看到Command(SceneNode&amp;)的方式创建这些命令,从而能够正确设置它?换句话说,我怎么能得到这个:

Command::Command(SceneNode& n)
: action()
// , category(Category::None)
, node(n)
{}

目前在stl_map.h中给出了一个我不明白的错误,可能是因为在Player的函数中错误地调用了Command构造函数

提前致谢,对这个冗长的问题感到抱歉,但我认为上下文是必要的。

1 个答案:

答案 0 :(得分:2)

如果我正确理解了这个问题,我认为你正在观察std::map::operator[]的创建 - 如果不存在并返回 - 引用行为:

  

如果[key]与容器中任何元素的键不匹配,该函数将使用该键插入一个新元素,并返回对其映射值的引用。请注意,即使没有为元素指定映射值(使用其默认构造函数构造元素),这也总是会将容器大小增加1。

如果您想自己构建Command对象(可能是通过非default constructor),您可能需要调用std::map::insertstd::map::emplace,具体取决于语义你想要(以及你的编译器对更新标准的支持),而不是使用operator[]

将这些全部拉到一起,尝试这样的事情:

Command cmd(theSceneNode);
cmd.action = derivedAction<SpaceCraft>(SpaceCraftMover(-playerSpeed, 0.f));
// more command setup, possibly
mActionBinding.insert(std::make_pair(MoveLeft, cmd));
// or possibly, mActionBinding.insert(std::make_pair(MoveLeft, std::move(cmd)));