Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
C++ для начинающих (Стенли Липпман) 3-е хххх.pdf
Скачиваний:
86
Добавлен:
30.05.2015
Размер:
5.92 Mб
Скачать

С++ для начинающих

604

Функцию-член можно также объявить со спецификатором volatile (он был введен в

разделе 3.13). Объект класса объявляется как volatile, если его значение изменяется способом, который не обнаруживается компилятором (например, если это структура данных, представляющая порт ввода/вывода). Для таких объектов вызываются только

class Screen { public:

char poll() volatile; // ...

};

функции-члены с тем же спецификатором, конструкторы и деструкторы: char Screen::poll() volatile { ... }

13.3.6. Объявление mutable

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

const Screen cs ( 5, 5 );

Если мы хотим прочитать символ, находящийся в позиции (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

_cursor

=

row +

c

- 1;

}

еетаковой непросто. Определение move() выглядит следующим образом:

}

Обратите внимание, что move()изменяет член класса _cursor, следовательно, не может быть объявлена константной.

Но почему нельзя модифицировать _cursor для константного объекта класса Screen? Ведь _cursor это просто индекс. Изменяя его, мы не модифицируем содержимое

С++ для начинающих

605

экрана, а лишь пытаемся установить позицию внутри него. Модификация _cursor должна быть разрешена несмотря на то, что у класса Screen есть спецификатор const.

Чтобы разрешить модификацию члена класса, принадлежащего константному объекту, объявим его изменчивым (mutable). Член с таким спецификатором не бывает константным, даже если он член константного объекта. Его можно обновлять, в том числе функцией-членом со спецификатором const. Объявлению изменчивого члена

class Screen {

 

public:

 

// функции-члены

 

private:

_screen;

string

mutable string::size_type

_cursor; // изменчивый член

short

_height;

short

_width;

класса должно предшествовать ключевое слово mutable:

};

Теперь любая константная функция способна модифицировать _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