class Screen {
public:
inline char get( int, int );
// объявления других функций-членов не изменяются
};
Определение функции следует после объявления класса. При этом слово inline можно опустить:
char Screen::get( int r, int c )
{
move( r, c ); // устанавливаем _cursor
return get(); // вызываем другую функцию-член get()
}
Так как встроенные функции-члены должны быть определены в каждом исходном файле, где они вызываются, то встроенную функцию, не определенную в теле класса, следует поместить в тот же заголовочный файл, в котором определен ее класс. Например, представленные ранее определения move() и get() должны находиться в заголовочном файле Screen.h после определения класса Screen.
13.3.2. Доступ к членам класса
Говорят, что определение функции-члена принадлежит области видимости класса независимо от того, находится ли оно вне или внутри его тела. Отсюда следуют два вывода:
* в определении функции-члена могут быть обращения к любым членам класса, открытым или закрытым, и это не нарушает ограничений доступа;
* когда функция-член обращается к членам класса, операторы доступа "точка" и "стрелка" не необходимы.
Например:
#include string
void Screen::copy( const Screen &sobj )
{
// если этот объект и объект sobj - одно и то же,
// копирование излишне
// мы анализируем указатель this (см. раздел 13.4)
if ( this != &sobj )
{
_height = sobj._height;
_width = sobj._width;
_cursor = 0;
// создаем новую строку;
// ее содержимое такое же, как sobj._screen
_screen = sobj._screen;
}
}
Хотя _screen, _height, _width и _cursor являются закрытыми членами класса Screen, функция-член copy() работает с ними напрямую. Если при обращении к члену отсутствует оператор доступа, то считается, что речь идет о члене того класса, для которого функция-член вызвана. Если вызвать copy() следующим образом:
#include quot;Screen.hquot;
int main()
{
Screen s1;
// Установить s1
Screen s2;
s2.copy(s1);
// ...
}
то параметр sobj внутри определения copy() соотносится с объектом s1 из функции main(). Функция-член copy() вызвана для объекта s2, стоящего перед оператором “точка”. Для такого вызова члены _screen, _height, _width и _cursor, при обращении к которым внутри определения этой функции нет оператора доступа, – это члены объекта s2. В следующем разделе мы рассмотрим доступ к членам класса внутри определения функции-члена более подробно и, в частности, покажем, как для поддержки такого доступа применяется указатель this.
13.3.3. Закрытые и открытые функции-члены
Функцию-член можно объявить в любой из секций public, private или protected тела класса. Где именно это следует делать? Открытая функция-член задает операцию, которая может понадобиться пользователю. Множество открытых функций-членов составляет интерфейс класса. Например, функции-члены home(), move() и get() класса Screen определяют операции, с помощью которых программа манипулирует объектами этого типа.,/p
Поскольку мы прячем от пользователей внутреннее представление класса, объявляя его члены закрытыми, то для манипуляции объектами типа Screen необходимо предоставить открытые функции-члены. Такой прием – сокрытие информации – защищает написанный пользователем код от изменений во внутреннем представлении.
Внутреннее состояние объекта класса также защищено от случайных изменений. Все модификации объекта производятся с помощью небольшого набора функций, что существенно облегчает сопровождение и доказательство правильности программы.
До сих пор мы встречались лишь с функциями, поддерживающими доступ к закрытым членам только для чтения. Ниже приведены две функции set(), позволяющие пользователю модифицировать объект Screen. Добавим их объявления в тело класса:
class Screen {
public:
void set( const string &s );
void set( char ch );
// объявления других функций-членов не изменяются
};
Далее следуют определения функций:
void Screen::set( const string &s )
{ // писать в строку, начиная с текущей позиции курсора
int space = remainingSpace();
int len = s.size();
if ( space len ) {
cerr "Screen: warning: truncation:"
"space: " space
"string length: " len endl;
len = space;
}
_screen.replace( _cursor, len, s );