Для примера объявления класса рассмотрим реализацию типа String (строка символов и работа в ней) .
const int MAX= 256;
class String
{
private: // необязательное ключевое слово
unsigned char len; // определение внутренних
char line[MAX]; // данных
public: // операции
void fill(char *); // заполнение строки
int length()
{return len;} // длина строки
void write()
{cout << line;} // вывод строки
void writeln() { write();
{cout << ‘\n’;}
char & index (int i); //получение элемента строки
// по индексу
};
Имя типа String, которое следует за ключевым словом class, будет представлять новый тип, введенный пользователем. Это имя затем может быть использовано для объявления переменных (объектов) данного типа:
String s1;
Тело класса, заключенное в фигурные скобки и ограниченное точкой с запятой, содержит определение членов класса. Член класса включает член-данные – данные, характеризующие абстракцию (в данном случае длину строки и ее содержимое), а также член-функции – операции, которые могут быть выполнены над объектами данного типа.
В нашем примере используются ключевые слова private и public. Кроме них может использоваться ключевое слово protected. Эти слова управляют доступом к членам класса. Если члены класса объявлены после ключевого слова public, то они считаются общими, т.е. открытыми для доступа из любой точки программы в области видимости объекта типа String.
Ключевые слова private и protected говорят о том, что следующие за ними члены доступны только для член-функций данного класса. Подобное ограничение доступа носит название «сокрытие информации». Различие между доступом к членам, объявленным как private и как protected будет разъяснено много позже. В нашем случае эти слова эквивалентны.
Хорошим стилем считается объявление член-данных в части private, а член-функций в части public. Это обеспечивает следующие преимущества:
- при необходимости корректировки член-данных в определении класса изменения надо проводить только в функциях, являющихся членами данного класса;
- обеспечивается защита член-данных в определении класса от случайных изменений и несанкционированного доступа.
Если при объявлении класса ключевые слова public, private, protected опущены, то подразумевается доступ private.
Член-данные len и line в нашем примере – скрытые, т. е. они доступны только для член-функций. Все член-функции у нас объявлены в части public и поэтому доступны из любой точки программы в области видимости объекта типа String. Доступ к членам public осуществляется с помощью операций выбора «.» и ->. :
String s1,* ps2;
s1.fill(«Привет»);
ps2->length();
Член-функции могут быть также внешними и встраиваемыми. Если тело функции приведено внутри описания класса, такая функция будет неявно встраиваемой.
В классе String встраиваемыми член-функциями являются length(), write(), writeln(). Если определение член-функции вынесено за пределы описания класса и этому описанию не предшествует ключевое слово inline, то функция является внешней.
При определении член-функции вне описания класса имя функции в заголовке определения должно быть уточнено именем класса с помощью операции :: следующим образом:
Имя класса :: имя функции
Например, определение член-функции fill, выполняющей заполнение объекта String, будет выглядеть так:
void String :: fill(char *str)
{for(len=0;line[lean]=str[len];len++);
}
Если при определении член-функции используется ключевое слово inline, то такая функция будет явно встраиваемой.
//Выбор символа строки по заданному индексу
inline char & String::index(int i)
{ if (i==len)
{cout << «Индекс за границей строки\n»;
return line[0];
}
else return line[i];
}
Важно отметить, что при определении член-функций класса доступ к другим членам этого же класса (как и public, так и private) осуществляется просто по имени без дополнительной2 операции уточнения. Это вызвано тем, что всем член-функциям передается неявный аргумент – указатель на объект класса, для которого данная функция вызывается (указатель this). Все неуточненные члены в теле член-функции неявно уточняются этим указателем.
При определении класса, так же как и при определении структуры, память не выделяется. Для выделения памяти под объект класса должна быть выделена переменная (String ss).
Неудобством при работе с объектами нашего класса String является то, что нельзя проинициализировать переменную этого класса при объявлении.
На оператор объявления
String ss= «Вася»
будет выдано сообщение об ошибке.
Заполнить переменную информацией можно с помощью функции fill:
ss.fill(«Вася + Маша»);
Если это действие не будет выполнено, то содержимое переменной будет либо нулевым, если она объявлена на глобальном уровне, либо неопределенным, если это локальная переменная.