_cursor += len - 1;
}
void Screen::set( char ch )
{
if ( ch == '\0' )
cerr "Screen: warning: "
"null character (ignored).\n";
else _screen[_cursor] = ch;
}
В реализации класса Screen мы предполагаем, что объект Screen не содержит двоичных нулей. По этой причине set() не позволяет записать на экран нуль.
Представленные до сих пор функции-члены были открытыми, их можно вызывать из любого места программы, а закрытые вызываются только из других функций-членов (или друзей) класса, но не из программы, обеспечивая поддержку другим операциям в реализации абстракции класса. Примером может служить функция-член remainingSpace класса Screen(), использованная в set(const string&).
class Screen {
public:
// объявления других функций-членов не изменяются
private:
inline int remainingSpace();
};
remainingSpace() сообщает, сколько места осталось на экране:
inline int Screen::remainingSpace()
{
int sz = _width * _height;
return ( sz - _cursor );
}
(Детально защищенные функции-члены будут рассмотрены в главе 17.)
Следующая программа предназначена для тестирования описанных к настоящему моменту функций-членов:
#include "Screen.h"
#include iostream
int main() {
Screen sobj(3,3); // конструктор определен в разделе 13.3.4
string init("abcdefghi");
cout "Screen Object ( "
sobj.height() ", "
sobj.width() " )\n\n";
// Задать содержимое экрана
string::size_type initpos = 0;
for ( int ix = 1; ix = sobj.width(); ++ix )
for ( int iy = 1; iy = sobj.height(); ++iy )
{
sobj.move( ix, iy );
sobj.set( init[ initpos++ ] );
}
// Напечатать содержимое экрана
for ( int ix = 1; ix = sobj.width(); ++ix )
{
for ( int iy = 1; iy = sobj.height(); ++iy )
cout sobj.get( ix, iy );
cout "\n";
}
return 0;
}
Откомпилировав и запустив эту программу, мы получим следующее:
Screen Object ( 3, 3 )
abc
def
ghi
13.3.4. Специальные функции-члены
Существует специальная категория функций-членов, отвечающих за такие действия с объектами, как инициализация, присваивание, управление памятью, преобразование типов и уничтожение. Такие функции называются конструкторами. Они вызываются компилятором неявно каждый раз, когда объект класса определяется или создается оператором new. В объявлении конструктора его имя совпадает с именем класса. Вот, например, объявление конструктора класса Screen, в котором заданы значения по умолчанию для параметров hi, wid и bkground:
class Screen {
public:
Screen( int hi = 8, int wid = 40, char bkground = '#');
// объявления других функций-членов не изменяются
};
Определение конструктора класса Screen выглядит так:
Screen::Screen( int hi, int wid, char bk ) :
_height( hi ), // инициализировать _height значением hi
_width( wid ), // инициализировать _width значением wid
_cursor ( 0 ), // инициализировать _cursor нулем
_screen( hi * wid, bk ) // размер экрана равен hi * wid
// все позиции инициализируются
// символом '#'
{ // вся работа проделана в списке инициализации членов
// этот список обсуждается в разделе 14.5
}
Каждый объявленный объект класса Screen автоматически инициализируется конструктором:
Screen s1; // Screen(8,40,'#')
Screen *ps = new Screen( 20 ); // Screen(20,40,'#')
int main() {
Screen s(24,80,'*'); // Screen(24,80,'*')
// ...
}
(В главе 14 конструкторы, деструкторы и операторы присваивания рассматриваются более подробно. В главе 15 обсуждаются конвертеры и функции управления памятью.)
13.3.5. Функции-члены со спецификаторами const и volatile
Любая попытка модифицировать константный объект из программы обычно помечается компилятором как ошибка. Например:
const char blank = ' ';
blank = '\n'; // ошибка
Однако объект класса, как правило, не модифицируется программой напрямую. Вместо этого вызывается та или иная открытая функция-член. Чтобы не было "покушений" на константность объекта, компилятор должен различать безопасные (те, которые не изменяют объект) и небезопасные (те, которые пытаются это сделать) функции-члены:
const Screen blankScreen;
blankScreen.display(); // читает объект класса
blankScreen.set( '*' ); // ошибка: модифицирует объект класса
Проектировщик класса может указать, какие функции-члены не модифицируют объект, объявив их константными с помощью спецификатора const: