Russian Qt Forum
Ноябрь 23, 2024, 03:29 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: 1 [2] 3   Вниз
  Печать  
Автор Тема: mutable метод?  (Прочитано 13588 раз)
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #15 : Апрель 05, 2015, 13:39 »

А что это и к чему?
Записан
andrew.k
Гость
« Ответ #16 : Апрель 08, 2015, 21:20 »

А что это и к чему?
Это типа, если совесть мучает писать везде mutable (и поделом), то сохраняешь не константный this и творишь чудеса в решете)

А по сабжу: очень некрасиво как-то выходит.
Вот захотел я как клиент класса узнать количество файлов, а там целая жизнь происходит, что-то обновляется, что-то загружается, непрозрачно, нелогично, некрасиво. А я просто хотел число, чтобы на форме показать.

Может добавить "dirty state" и пусть клиент сам проверяет.
Код
C++ (Qt)
if(obj->isDirty() /*|| obj->isReady()*/)
  obj->update();
А при этому GetNumFiles() const должен возвращать значение, которое даже в состоянии "dirty" должно иметь смысл, потому что и до и после обновления оно не должно меняться, у нас ведь логическая константность требуется?
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #17 : Апрель 09, 2015, 08:08 »

А по сабжу: очень некрасиво как-то выходит.
Вот захотел я как клиент класса узнать количество файлов, а там целая жизнь происходит, что-то обновляется, что-то загружается, непрозрачно, нелогично, некрасиво. А я просто хотел число, чтобы на форме показать.
Пример
Код
C++ (Qt)
virtual QSize sizeHint() const
Просто хотел узнать размер, а там целая жизнь произошла! Все позиции чайлд виджетов изменились, а объявлен const

Видимо дело в том что кроме эстетических соображений "нелогично/некрасиво" (которые непонятно откуда берутся) есть еще и логика задачи, и она не всегда совпадает с формальными требованиями.

Может добавить "dirty state" и пусть клиент сам проверяет.
Код
C++ (Qt)
if(obj->isDirty() /*|| obj->isReady()*/)
  obj->update();
Это уже звучало, клиент использует геттеры очень массово. Требование окружать каждый геттер проверкой - это возложить на клиента массу забот которые ему совершенно не нужны.

Также заметим что ситуация эта возникает только в одном из унаследованных классов, в остальных все прекрасно ложится "по книжке"
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #18 : Апрель 09, 2015, 09:00 »

Пример
Код
C++ (Qt)
virtual QSize sizeHint() const
Просто хотел узнать размер, а там целая жизнь произошла! Все позиции чайлд виджетов изменились, а объявлен const
А почему в sizeHint все позиции детей меняются? На каком основании?
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #19 : Апрель 09, 2015, 09:09 »

А почему в sizeHint все позиции детей меняются? На каком основании?
Не суть. Главное - что выполняется "отложенное действие", лайаут не бросается все пересчитывать при каждом изменении, а взводит флажок dirty. Когда же клиент вызывает пересчет - для него это const операция, и это правильно. 
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #20 : Апрель 09, 2015, 09:16 »

Не суть. Главное - что выполняется "отложенное действие", лайаут не бросается все пересчитывать при каждом изменении, а взводит флажок dirty. Когда же клиент вызывает пересчет - для него это const операция, и это правильно.  
Значит sizeHint ничего не пересчитывает и спокойно может быть const. В чем проблема?
Тема началась с того, что вы хотели менять состояние объекта из const методов - так нельзя. Но вы можете из const методов менять состояние других объектов, которыми объект может владеть. Что и показывал мой пример.

В контексте вашей проблемы:
Код
C++ (Qt)
class ImageMovie
{
public:
   int getFileNum() const
   {
       if( !m_cache->size() )
           m_cache->preloadFiles();    // вызываем не const-метод кеша. Меняем состояние объекта кеша, а не нашего
       return m_cache->size();
   }
 
private:
   ImageCachePtr m_cache;
};
 
« Последнее редактирование: Апрель 09, 2015, 09:46 от Old » Записан
andrew.k
Гость
« Ответ #21 : Апрель 09, 2015, 15:13 »

А почему в sizeHint все позиции детей меняются? На каком основании?
Не суть. Главное - что выполняется "отложенное действие", лайаут не бросается все пересчитывать при каждом изменении, а взводит флажок dirty. Когда же клиент вызывает пересчет - для него это const операция, и это правильно.  
Ничего он не выставляет и не двигает никуда детей.
Просто возвращает текущее значение.
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #22 : Апрель 10, 2015, 06:07 »

Ничего он не выставляет и не двигает никуда детей.
Просто возвращает текущее значение.
Я тоже так думал (на основании 1-2 экспериментов). Кстати вот как решают это в Qt
Код
C++ (Qt)
QSize QBoxLayout::sizeHint() const
{
   Q_D(const QBoxLayout);
   if (d->dirty)
       const_cast<QBoxLayout*>(this)->d_func()->setupGeom();
   return d->sizeHint;
}
Записан
_Bers
Бывалый
*****
Offline Offline

Сообщений: 486


Просмотр профиля
« Ответ #23 : Апрель 11, 2015, 10:40 »

Кстати вот как решают это в Qt
Код
C++ (Qt)
QSize QBoxLayout::sizeHint() const
{
   Q_D(const QBoxLayout);
   if (d->dirty)
       const_cast<QBoxLayout*>(this)->d_func()->setupGeom();
   return d->sizeHint;
}

Код:
const QBoxLayout trololo;
trololo.sizeHint(); // <--- UB

Изменение состояния объекта, рожденного константой есть UB.

На практике сталкивался с случаями,
когда компилятор размещал такие объекты в памяти "только для чтения".

В результате, функции которые пытались изменить состояние объекта
отваливались с аккцесс-виолейшеном.

const_cast можно применять только в 2х случаях:
1. Когда вы точно знаете, что состояние объекта изменено не будет.
Например, студенты медицинского факультета написали библиотеку,
в которой вообще нигде нет ни одного const.

Но тем не менее, вы знаете что часть методов хоть и не const,
но на самом деле состояние объекта не изменяют

В этом случае можно скастить аргумент,
что бы компилятор позволил вызовы функций.

2. Когда вы точно знаете, что объект,
над которым творят такие бесчеловеченые издевательства,
был рожден не как константа.



Записан
Авварон
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3260


Просмотр профиля
« Ответ #24 : Апрель 11, 2015, 19:58 »


Код:
const QBoxLayout trololo;
trololo.sizeHint(); // <--- UB

Очевидно, что это не так. Иначе бы кутешники не пользовались этим повсеместно (уж кто-кто, а они поддерживают тучу компиляторов и платформ)
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #25 : Апрель 11, 2015, 21:25 »

Очевидно, что это не так. Иначе бы кутешники не пользовались этим повсеместно (уж кто-кто, а они поддерживают тучу компиляторов и платформ)
Разговор идет не про Qt, а про константные объекты.
Например, при компиляции прошивок для микроконтроллеров, компилятор обязан все константные объекты выносить в секции, которые размещаются в read only памяти. ОЗУ в МК ограниченно, и все по максимуму стараются перенести в EEPROM.
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #26 : Апрель 12, 2015, 09:16 »

Но тем не менее, вы знаете что часть методов хоть и не const,
но на самом деле состояние объекта не изменяют
Спасибо за подробные объяснения, я понял, просто интересует др аспект. Разумеется "изменение состояния" истинное, с этим никто не спорит. Но с др стороны все эти изменения замкнуты внутри класса. Очень плохо посвящать др классы в эти внутренние подробности, для них геттеры должны оставаться const. Вариант с "выносом указателя" на мой взгляд еще хуже, const_cast легко найти, их всего 2 (если не 1). А с указателем "концы в воду".

И, повторюсь, интересно посмотреть на это с точки зрения иерархии классов, напр
Код
C++ (Qt)
virtual int CSinglePicture::FramesTotal( void ) const;   // никаких проблем, чистейшей воды const  
virtual int CAnimatedPicture::FramesTotal( void ) const;   // тоже const  
virtual int CMultiFilePicture::FramesTotal( void ) const;   // вот тут (и только тут) нужен GetNumFiles а он не const
Конечно это не фатальная проблема, я спокойно отношусь к любым приведениям, типа "надо так надо, значит лучшего решения пока нет". Просто интересно какие еще возможности.

Спасибо
Записан
_Bers
Бывалый
*****
Offline Offline

Сообщений: 486


Просмотр профиля
« Ответ #27 : Апрель 12, 2015, 21:22 »

Очевидно, что это не так. Иначе бы кутешники не пользовались этим повсеместно (уж кто-кто, а они поддерживают тучу компиляторов и платформ)

у языка с++ есть стандарт.
в котором все прописано.

Записан
Авварон
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3260


Просмотр профиля
« Ответ #28 : Апрель 13, 2015, 09:20 »

Разговор идет не про Qt, а про константные объекты.
Например, при компиляции прошивок для микроконтроллеров, компилятор обязан все константные объекты выносить в секции, которые размещаются в read only памяти. ОЗУ в МК ограниченно, и все по максимуму стараются перенести в EEPROM.

Объекты, созданные на стеке? Ну-ну.
А если вы делаете глобал не-под статики то у меня для вас плохие новости - это один сплошной UB, даже без const.
Записан
andrew.k
Гость
« Ответ #29 : Апрель 13, 2015, 16:10 »

Ничего он не выставляет и не двигает никуда детей.
Просто возвращает текущее значение.
Я тоже так думал (на основании 1-2 экспериментов). Кстати вот как решают это в Qt
Код
C++ (Qt)
QSize QBoxLayout::sizeHint() const
{
   Q_D(const QBoxLayout);
   if (d->dirty)
       const_cast<QBoxLayout*>(this)->d_func()->setupGeom();
   return d->sizeHint;
}
Читеры! Я вообще смотрел QWidget, в лейаут не догадался.

Странно, что мешало  им сделать d->sizeHint mutable? В этом случае это было бы оправдано.
Ведь он по сути хранит кешированное значение. Так был бы более красивый и понятный код.
« Последнее редактирование: Апрель 13, 2015, 16:13 от andrew.k » Записан
Страниц: 1 [2] 3   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.382 секунд. Запросов: 23.