我使用const QMap
从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;
答案 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;
}
我的结论是,问题中的代码没有任何问题。要么编译器有错误,要么问题中缺少重要信息,这与我上面的重建不同。