Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
OOP_otvety_k_ekzamenu.doc
Скачиваний:
61
Добавлен:
13.04.2015
Размер:
786.94 Кб
Скачать

19. Физическое и логическое постоянство объектов. Модификатор mutable.

Если мы будем оперировать например с преобразованием объекта-дату в строку, то мы столкнемся с проблемой сохранения строки во временном массиве, так как после возвращения из функции ту память, под которую мы выделили для строки в стеке будет считаться не занятой и может быть в любой момент перезаписана чем-либо другим. Решением этой проблемы будет использование либо глобального, либо статического локального буфера памяти, имеющего постоянное место хранения.

//тело класса

// Функция преобразования даты в строку

const char* ToString ( char _sep ) const

{

// Размещаем результирующую строку в статическом локальном массиве

static char tempBuf[ 11 ];

sprintf( tempBuf, "%d%c%d%c%d", m_Year, _sep, m_Month, _sep, m_Day );

return tempBuf;

}

//выведим на экран ОДНУ дату-объект

Date d( 2013, 5, 3 );

const char * str = d.ToString( '/' );

std::cout << str << std::endl;

Если же мы будем пытаться выводить два и более дат-объектов, то мы будем выводить на экран только последний созданный объект.

Решить указанную проблему можно размещением буфера для результирующей строки непосредственно в памяти объекта-даты. В таком случае каждый объект получил бы индивидуальный ни с кем не разделяемый буфер. Однако, такой подход ведет к противоречию условия неизменности объекта — с логической точки зрения преобразование даты в строку не должно изменять состояние объекта-даты, что подчеркнуто модификатором const, а физически состояние измениться заполнением буфера символов.

Для случаев, когда в классе часть переменных-членов не образует логической основы понятия, а носит лишь вспомогательный характер, некий низкоуровневый механизм реализации, предусмотрено ключевое слово mutable. Такой модификатор переменной-члена разрешает изменение состояния даже если это происходит внутри функции-члена с модификатором const.

//тело класса

// Буфер для строкового представления. Можно изменять даже в const-методах

mutable char m_tempBuf[ 10 ];

public:

// ...

// Функция преобразования даты в строку

const char* ToString ( char _sep ) const

{

// Размещаем результирующую строку в мутирующем буфере внутри объекта

sprintf( m_tempBuf, "%d%c%d%c%d", m_Year, _sep, m_Month, _sep, m_Day );

return tempBuf;

}

Представляется возможным повысить производительность операции ToString для класса Date, если избежать переформирования строкового представления при отсутствии изменения состояния данных о годе, месяце, дне. Для этого понадобится еще одна “мутирующая” переменная-член, означающая, что объект не менял своего состояния, соответственно, буфер содержит нужные символы:

Буфер для строкового представления. Можно изменять даже в const-методах

mutable char m_tempBuf[ 10 ];

// Флаг валидности содержимого буфера

mutable bool m_BufferValid;

Флаг устанавливается в значение false при создании объекта

Флаг также устанавливается в значение false при изменении состояния объекта

// Функция преобразования даты в строку

const char* ToString ( char _sep ) const

{

// Переформируем буфер только если он в неактуальном состоянии

if ( ! m_BufferValid )

{

// Размещаем результирующую строку в мутирующем буфере внутри объекта

sprintf( m_tempBuf, "%d%c%d%c%d", m_Year, _sep, m_Month, _sep, m_Day );

// Буфер теперь актуален

m_Buffervalid = true;

}

return tempBuf;

}

Если таких “мутирующих” полей в классе появляется много, это скорее всего свидетельствует о необходимости выноса части состояния объекта в другой вспомогательный объект, отдельно отвечающий за физическую часть.

//тело класса

struct StringRepr

{

char m_tempBuf[ 10 ];

bool m_isValid;

}

StringRepr* m_pStringRepr;

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

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]