2

我正在尝试按键访问地图数据结构的元素,但出现编译器错误。我已经使用 typedefs 定义了我的地图数据结构,以简化地图实例化的语法。如您所见,键是类型string,数据是自定义GameComponent对象:

typedef map<string, GameComponent*> ComponentMap;
typedef map<string, GameComponent*>::iterator ComponentMapIter;
typedef map<string, GameComponent*>::const_iterator ComponentMapCIter;

在 的派生类中GameComponent,我正在为存储在我的地图中的每个唯一 GameComponent 对象创建标准复合模式方法以及访问器。但是,使用数组下标运算符访问访问器中的对象会导致编译器错误:

void Character::add(const string& key, GameComponent* comp)
{
    m_components->insert( make_pair(key, comp) );
}

void Character::remove(const string& key)
{
    m_components->erase(key);
}

Armor* Character::getArmor() const
{
    // ERROR:
    return static_cast<Armor*>(m_components["Armor"]);
}

Weapon* Character::getWeapon() const
{
    // ERROR:
    return static_cast<Weapon*>(m_components["Weapon"]);
}

Attributes* Character::getAttributes() const
{
    // ERROR:
    return static_cast<Attributes*>(m_components["Attributes"]);
}

编译器错误的输出显示“无效类型”错误,这让我摸不着头脑:

/Users/Dylan/Desktop/RPG/character.cpp: In member function 'Armor* Character::getArmor() const':
/Users/Dylan/Desktop/RPG/character.cpp:66: error: invalid types 'ComponentMap* const[const char [6]]' for array subscript
/Users/Dylan/Desktop/RPG/character.cpp: In member function 'Weapon* Character::getWeapon() const':
/Users/Dylan/Desktop/RPG/character.cpp:71: error: invalid types 'ComponentMap* const[const char [7]]' for array subscript
/Users/Dylan/Desktop/RPG/character.cpp: In member function 'Attributes* Character::getAttributes() const':
/Users/Dylan/Desktop/RPG/character.cpp:76: error: invalid types 'ComponentMap* const[const char [11]]' for array subscript
4

3 回答 3

6

由于operator[]在 a std::mapis notconst中,您不能在const方法中使用它(当然是在成员上)。

在 C++11 之前使用at(C++11) 或find& 迭代器。

相关:为什么 std::map 没有 const 访问器?

于 2012-12-26T18:55:31.937 回答
6

似乎m_components是 type ComponentMap*。当您编写m_components["Armor"]编译器时,编译器会将其解释为对 s"Armor"的动态数组的第 - 个元素的访问ComponentMap,这没有任何意义。

你想要的是(*m_components)["some string"]. 这将调用operator[]of ComponentMap,但正如 Luchian Grigore 和 Olaf Dietsche 所提到的,std::map::operator[]没有 const 重载,所以这也会失败。剩下的唯一选择是使用find.

简化版将是:

Armor* Character::getArmor() const
{
    return static_cast<Armor*>(m_components->find("Armor")->second);
}

Weapon* Character::getWeapon() const
{
    return static_cast<Weapon*>(m_components->find("Weapon")->second);
}

Attributes* Character::getAttributes() const
{
    return static_cast<Attributes*>(m_components->find("Attributes")->second);
}

此代码与原始示例的行为不同,如果m_components没有"Armor","Weapon""Attributes"元素,则会失败。我们能得到的最接近的是显式处理元素的缺失并返回0,或者nullptr如果您使用 C++11。

最终正确的 C++03 兼容版本:

Armor* Character::getArmor() const
{
    ComponentMapCIter i = m_components->find("Armor");
    if (i != m_components->end())
        return static_cast<Armor*>(i->second);
    return 0;
}

Weapon* Character::getWeapon() const
{
    ComponentMapCIter i = m_components->find("Weapon");
    if (i != m_components->end())
        return static_cast<Weapon*>(i->second);
    return 0;
}

Attributes* Character::getAttributes() const
{
    ComponentMapCIter i = m_components->find("Attributes");
    if (i != m_components->end())
        return static_cast<Attributes*>(i->second);
    return 0;
}
于 2012-12-26T19:04:17.470 回答
2

getArmor(),getWeapon()getAttributes()已定义const,但m_components[] 可能会修改m_components. 所以你要么不定义你的方法const,要么std::map::find改用它。

Armor* Character::getArmor() const
{
    auto i = m_components->find("Armor");
    if (i != m_components->end())
        return static_cast<Armor*>(i->second);

    return nullptr;
}
于 2012-12-26T18:56:03.153 回答