更改const函数内的地图内容

时间:2015-09-16 13:50:34

标签: c++ qt const qmap

我使用const QMapQMap::find()获取迭代器,通过该迭代器,我可以更改地图的内容。在我看来,这违反了对象的逻辑常量。我错了吗?

这是否允许,因为编译器无法识别由于Qt API而被更改的内容?

void OpticalTrackingSystem::UpdateTrackability(const QUuid &uid) const
{
  // m_ObjectsToTrack is a member, therefore const
  ObjectMap::iterator it = m_ObjectsToTrack.find(uid);

  it.value().m_Trackable = true; // assignment to const!
  it.value().m_Moved = false;
}

如果重要,我的编译器是MSVC。

修改ObjectMap定义为

struct ObjectProperties
{
    ObjectProperties(const ObjectToTrack &obj)
        : m_Obj(obj) { m_Trackable = false; m_Moved = false; }
    ObjectToTrack m_Obj;
    bool m_Trackable;
    bool m_Moved;
};
typedef QMap<QUuid, ObjectProperties> ObjectMap; 

2 个答案:

答案 0 :(得分:1)

const增强了数据隐藏和封装,以提供完整的编译时安全性。

C ++仅支持一个级别的常量。在您的示例中,这意味着您的函数无法添加,删除或替换地图中的元素。然而操纵其成员是公平的游戏。

答案 1 :(得分:1)

QMap包含const和非const find方法:

      iterator find(const Key & key)
const_iterator find(const Key & key) const

就像std::map

      iterator find (const key_type& k);
const_iterator find (const key_type& k) const;

QMap迭代器在value()

的常量上有所不同
      T& QMap::      iterator::value() const;
const T& QMap::const_iterator::value() const;

所以你不应该通过返回的迭代器来操作值。但是你将返回的迭代器分配给ObjectMap::iterator - 我希望在那时出现错误,但如果没有ObjectMap及其迭代器的定义,我就无法测试它。

当然,以下MCVE演示了编译时错误:

#include <QMap>

int main()
{
    const QMap<int,float> m{{1, 1.0}, {5, 5.0}};
    auto it = m.find(1);
    it.value() = 2.0;
    //         ^
    // error: assignment of read-only location
    //       ‘it.QMap<Key, T>::const_iterator::value<int, float>()’
}

显式分配迭代器会产生另一个预期错误:

#include <QMap>

int main()
{
    const QMap<int,float> m{{1, 1.0}, {5, 5.0}};
    QMap<int,float>::iterator it = m.find(1);
    //                                     ^
    // error: conversion from ‘QMap<int, float>::const_iterator’
    //        to non-scalar type ‘QMap<int, float>::iterator’ requested
    it.value() = 2.0;
}

(我在两种情况下都用g++ -std=c++11 -Wall -Wextra -fPIC $(pkg-config --cflags Qt5Core)编译)

修改

在问题中没有正确的例子的情况下,我试图推断缺失的声明。但是当我尝试编译时,我仍然从gcc中得到所需的错误:

#include <QMap>
#include <QUuid>

struct ObjectToTrack
{
};

struct ObjectProperties
{
    ObjectProperties(const ObjectToTrack &obj)
        : m_Obj(obj), m_Trackable(), m_Moved() {}
    ObjectToTrack m_Obj;
    bool m_Trackable;
    bool m_Moved;
};
typedef QMap<QUuid, ObjectProperties> ObjectMap;

struct OpticalTrackingSystem
{
    ObjectMap m_ObjectsToTrack;
    void UpdateTrackability(const QUuid &uid) const;
};

void OpticalTrackingSystem::UpdateTrackability(const QUuid &uid) const
{
  ObjectMap::iterator it = m_ObjectsToTrack.find(uid);
  //                                                ^
  // error: conversion from ‘QMap<QUuid, ObjectProperties>::const_iterator’ to
  //        non-scalar type ‘QMap<QUuid, ObjectProperties>::iterator’ requested

  it.value().m_Trackable = true;
  it.value().m_Moved = false;
}

我的结论是,问题中的代码没有任何问题。要么编译器有错误,要么问题中缺少重要信息,这与我上面的重建不同。