|
Программирование >> Инициализация объектов класса, структура
#include <cstring> class Text { public: void bad( const string sparm ) const; private: char * text; void Text::bad( const string sparm ) const { text = parm.c str(); ошибка: нельзя модифицировать text for ( int ix = 0; ix < parm.size(); ++ix ) text[ix] = parm[ix]; плохой стиль, но не ошибка Модифицировать text нельзя, но это объект типа char*, и символы, на которые он указывает, можно изменить внутри константной функции-члена класса Text. Функция-член bad() демонстрирует плохой стиль программирования. Константность функции-члена не гарантирует, что объекты внутри класса останутся неизменными после ее вызова, причем компилятор не поможет обнаружить такую ситуацию. Константную функцию-член можно перегружать неконстантной функцией с тем же class Screen { public: char get(int x, int y); char get(int x, int y) const; ... списком параметров: В этом случае наличие спецификатора const у объекта класса определяет, какая из двух int main() { const Screen cs; Screen s; char ch = cs.get(0,0); вызывает константную функцию-член ch = s.get(0,0); вызывает неконстантную функцию-член функций будет вызвана: Хотя конструкторы и деструкторы не являются константными функциями-членами, они все же могут вызываться для константных объектов. Объект становится константным после того, как конструктор проинициализирует его, и перестает быть таковым, как только вызывается деструктор. Таким образом, объект со спецификатором const трактуется как константный с момента завершения работы конструктора и до вызова деструктора. class Screen { public: char poll() volatile; ... функции-члены с тем же спецификатором, конструкторы и деструкторы: char Screen::poll() volatile { ... } 13.3.6. Объявление mutable При объявлении объекта класса Screen константным возникают некоторые проблемы. Предполагается, что после инициализации объекта Screen, его содержимое уже нельзя изменять. Но это не должно мешать нам читать содержимое экрана. Рассмотрим следующий константный объект класса Screen: const Screen cs ( 5, 5 ); Если м1 хотим прочитать символ, находящийся в позиции (3,4), то попробуем сделать прочитать содержимое экрана в позиции (3,4) Увы! Это не работает cs.move( 3, 4 ); так: char ch = cs.get() ; Но такая конструкция не работает: move() - это не константная функция-член, и сделать inline void Screen::move( int r, int c ) if ( checkRange( r, c ) ) { int row = (r-1) * width; cursor = row + c - 1; модифицирует cursor ее таковой непросто. Определение move() выглядит следующим образом: Обратите внимание, что move() изменяет член класса cursor, следовательно, не может быть объявлена константной. Но почему нельзя модифицировать cursor для константного объекта класса Screen? Ведь cursor - это просто индекс. Изменяя его, м1 не модифицируем содержимое Функцию-член можно также объявить со спецификатором volatile (он был введен в разделе 3.13). Объект класса объявляется как volatile, если его значение изменяется способом, который не обнаруживается компилятором (например, если это структура данных, представляющая норт ввода/вывода). Для таких объектов вызываются только class Screen { public: функции-члены private: string screen; mutable string::size type cursor; изменчивый член short height; short width; класса должно предшествовать ключевое слово miutable: Теперь любая константная функция способна модифицировать cursor, и move() может быть объявлена константной. Хотя move() изменяет данный член, компилятор не считает move() - константная функция-член inline void Screen::move( int r, int c ) const { ... правильно: константная функция-член может модифицировать члены со спецификатором mutable cursor = row + c - 1; ... это ошибкой. Показанные в начале этого подраздела операции позиционирования внутри экрана теперь можно выполнить без сообщения об ошибке. Отметим, что изменчивым объявлен только член cursor, тогда как screen, height и width не имеют спецификатора mutable, поскольку их значения в константном объекте класса Screen изменять нельзя. Упражнение 13.3 Screen myScreen; Объясните, как будет вести себя copy() при следующих вызовах: myScreen.copy( myScreen ); Упражнение 13.4 экрана, а лишь пытаемся установить позицию внутри него. Модификация cursor должна быть разрешена несмотря на то, что у класса Screen есть спецификатор const. Чтобы разрешить модификацию члена класса, принадлежащего константному объекту, объявим его изменчивым (mutable). Член с таким спецификатором не бывает константным, даже если он член константного объекта. Его можно обновлять, в том числе функцией-членом со спецификатором const. Объявлению изменчивого члена
|
© 2006 - 2025 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |