Qt-QList const корректность
A QList<T *>
не может легко быть const-правильным. Рассмотрим функцию
void f(QList<T *> list)
{
list[0]->constFunction();
}
Я могу изменить f на
void f(QList<const T *> list)
Но тогда я не могу сделать
f(QList<T *>()); //Compile error
Больше, так как компилятор не может имплицитно привести QList<T *>
к QList<const T *>
. Однако я могу явно переинтерпретировать QList следующим образом:
template <typename T> inline QList<const T *> &constList(const QList<T *> &list)
{
return (QList<const T *> &)list;
}
Это позволяет мне использовать функцию шаблона constList
для приведения любого QList<T *>
в QList<const T *>
, как в
f(constList(QList<T *>()));
И это, кажется, работает нормально, но на самом деле безопасно ли это делать вот это?
2 ответа:
Функция приведения, которую вы рассматриваете, ...
template< class T > inline QList<T const*>& constList( QList<T*> const& list ) { return reinterpret_cast< QList<T const*>& >( const_cast< QList<T*>& >( list ) ); }
... может быть практичным (вероятно,
QList
не изменяет своего объектного представления в зависимости отconst
-ности типа элемента), но он может нарушатьconst
корректность.Во-первых, потому что отбрасывание
const
- ности самого списка не являетсяconst
правильным: это позволяет изменить исходный списокconst
.Но даже если этот формальный Аргумент
const
будет удален, как ...template< class T > inline QList<T const*>& constList( QList<T*>& list ) { return reinterpret_cast< QList<T const*>& >( list ); }
... есть все еще проблема корректности
Причина в том, что список представляет собой дополнительный уровень косвенности, а с вашей функцией не является самим собойconst
.const
. Таким образом, после использования функции для получения ссылки на список с предполагаемым указателем на элементыconst
, Вы можете сохранить в этом списке указатель на то, что на самом деле являетсяconst
. И тогда вы можете использовать исходный список, чтобыизменить , что действительноconst
элемент, bang .Это та же самая причина, по которой существует нет неявного преобразования из
Что вы можете сделать без таких проблем, так это, имея ужеT**
вT const**
.const
список указателей на объекты, сделать так, чтобы они указывали на объектыconst
:Формальноtemplate< class T > inline QList<T const*> const& constList( QList<T*> const& list ) { return reinterpret_cast< QList<T const*> const& >( list ); }
Все еще существует
reinterpret_cast
как потенциальная проблема, но любой, кто специализируется на представленииQList
о постоянстве элементов, вероятно, заслуживает того, что они получили. :- )Ура и ХТ.,
Идея корректности Const слаба, и то, что вы обнаружили, является одной из многих причин. Концепция Constness захватывает только один бит семантики (change / don't change) и делает это настолько плохо и с довольно высокой стоимостью синтаксиса, что иногда даже требует дублирования кода.
Одна из проблем этой концепции заключается в том, что она плохо масштабируется по составу: например, мне было бы интересно передать функции вектор const неконстантных объектов, или вектор const неконстантных объектов, или вектор const const объектов и получение правильного синтаксиса является дорогостоящим... просто рассмотрим, как стандартный c++ был вынужден ввести
За эти годы я перешел от фанатичной позиции использования const корректности во всех возможных местах к противоположной позиции использования ее только там, где я вынужден. Опыт научил меня, что код, который не одержим корректностью const, становится чище, и что механизм корректности const никогда по-настоящему не ловит (по крайней мере, для me) любая логическая ошибка, но только ошибки о самой машине корректности const. К сожалению, корректность const-это одна из вещей в C++, которую вы вынуждены использовать, потому что правила C++ так говорят, и нет никакого способа просто избежать ее использования.const_iterator
, потому что это, конечно, отличается отconst iterator
.Я знаю, что меня понизят в должности, но мое предложение состоит в том, чтобы критически следить за всем, что Вы читаете о C++ на эту тему; держите мозг включенным и судите объективно. Просто потому, что было бы хорошо, если бы что-то было правдой (например, что const корректность помогает программисту) к сожалению, это не значит, что это действительно так.
Неважно, насколько велико имя, подписавшее книгу.Также помните, что если позиция требует, чтобы весь остальной мир был неправ, то, вероятно, неплохо быть хотя бы немного скептиком: большинство языков, даже те, которые родились после C++, не реализуют эту концепцию.