-1

我从const QMapusing获得了一个迭代器QMap::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; 
4

2 回答 2

1

QMap有 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;

迭代器的QMapconstness 确实不同value()

      T& QMap::      iterator::value() const;
const T& QMap::const_iterator::value() const;

所以你不应该能够通过返回的迭代器来操作这些值。但是您将返回的迭代器分配给 a 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;
}

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

于 2015-09-16T14:41:56.570 回答
1

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

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

于 2015-09-16T14:04:24.853 回答