Программирование на C и C++

Онлайн справочник программиста на C и C++

Введение в классы с++

Классы являются основой С++. Перед тем, как создать объект С++, необходимо определить его общую форму, используя ключевое слово class. Класс определяет новый тип данных, который соединяет в себе код и данные. По синтаксису класс аналогичен структуре. Однако класс также может включать функции, а не только данные. В качестве примера следующий класс определяет тип, который мы называем queue (очередь).

// создание класса очередь
Class queue {
int q[100];
int sloc, rloc;
public:
void init ();
void qput(int i);
int qget();
};

Класс может содержать публичные и частные части. По умолчанию все члены класса являются частными. Например, переменные q, sloc и rloc являются частными, то есть функции, не являю­щиеся членами класса, не имеют к ним доступа. Именно так достигается инкапсуляция: доступ к определенным частям данных может быть строго контролируемым. Хотя это и не показано в данном примере, можно также определить частные функции, которые могут вызываться только членами данного класса.

Для того, чтобы сделать части класса доступными из других частей программы, они должны быть объявлены с использованием ключевого слова public, которое и служит спецификатором доступа. Все переменные или функции, определенные после ключевого слова public, являются публичными, т.е. доступны для всех других функций в программе. В общем случае доступ к объекту из остальной части программы осуществляется с помощью функций со спецификатором доступа public. Хотя можно иметь переменные с публичным доступом, лучше ограничить их использова­ние или вовсе исключить из употребления. Вместо этого следует сделать все данные частными и контролировать доступ к ним с помощью функций, имеющих спецификатор доступа public. Та­ким образом публичные функции обеспечивают интерфейс к частным данным класса. Это помо­гает реализовать инкапсуляцию. Обратим внимание также, что после ключевого слова public сле­дует двоеточие.

Функции init(), qput() и qget() называются функциями-членами, потому что они являются час­тью класса queue. Переменные sloc, rloc и q называются переменными-членами (или членами дан­ных). Только функции-члены имеют доступ к частным членам класса, в котором они объявлены. Таким образом, только init(), qput() и qget() имеют доступ к sloc, rloc и q.

Как только определен класс, можно создать объект этого типа, используя имя класса. Факти­чески имя класса становится спецификатором нового типа данных. Например, следующий код создает объект с именем intqueue типа queue:

queue intqueue;

Также можно создать объекты при определении класса, помещая имена переменных после за­крывающей фигурной скобки, в точности так же, как это имеет место для структуры. Общий вид объявления класса следующий:

class имя_класса {
private данные и функции
public:
публичные данные и функции
} список объектов;

Разумеется, список объектов может быть пустым.

Внутри объявления класса queue использовались прототипы функции. Когда необходимо сооб­щить компилятору о функции, то следует использовать полную форму прототипа. Более того, в С++ все функции должны иметь прототипы. Прототипы не являются факультативными, как это было в С.

Когда приходит очередь написать реальный код функции-члена, необходимо указать компиля­тору, какому именно классу принадлежит эта функция. Например, ниже показан один из спосо­бов написания функции qput():

void queue::qput(int i)
{
if (sloc==99) {
cout << "Queue is full.\n";
return;
}
sIoc++;
q[sloc] = i;
}

Последовательность символов :: называется оператором области видимости (scope resolution operator). Он показывает принадлежность функции классу. В данном случае он говорит компи­лятору, что данная версия функции qput() принадлежит классу queue. Другими словами, функ­ция qput() находится в области видимости класса queue. В С++ несколько различных классов мо­гут использовать одинаковые имена функций. Компилятор знает, какая из них принадлежит какому классу благодаря оператору области видимости и имени класса.

Если вы рассматриваете часть программы, которая не входит в состав класса, то для вызова функции-члена класса необходимо использовать имя объекта и оператор «точка». Например, следующий фрагмент иллюстрирует вызов функции init() для объекта а:
queue a, b;
а.init();

Очень важно ясно себе представлять, что а и b являются двумя различными объектами. Это означает, что инициализация а не означает инициализацию b. Единственной связью между объек­тами а и b служит то, что они являются объектами одного и того же типа. Более того, копии переменных sloc, rloc и q объекта а совершенно независимы от соответствующих копий перемен­ных объекта b.

Использование имени класса и оператора «точка» необходимо только при вызове функции-члена извне класса. Внутри класса одна функция-член может вызывать другую функцию-член не­посредственно без использования оператора «точка». Аналогично функция-член может обра­щаться непосредственно к переменной-члену без использования оператора «точка». Представленная ниже программа демонстрирует все части класса queue:

#include <iostream.h>
// создание класса очередь
class queue {
int q[100];
int sloc, rloc;
public:
void init ();
void qput(int i);
int qget();
};
void queue::init ()
{
rloc = sloc = 0;
}
void queue::qput(int i)
{
if (sloc==99) {
cout << "Queue is full.\n";
return;
}
sIoc++ ; q[sloc] = i;
}
int queue::qget ()
{
if (rloc == sloc) {
cout << "Queue underflow.\n";
return 0;
}
rloc++;
return q[rloc];
}
int main ()
{
queue a, b; // создание двух объектов типа queue
а.init();
b.init();
a.qput(10);
b.qput(19);
a.qput(20);
b.qput(1);
cout << a.qget()<< " ";
cout << a.qget()<< " ";
cout << b.qget()<< " ";
cout << b.qget()<< "\n";
return 0;
}

Следует запомнить, что частные части объекта доступны только для функций, которые являют­ся членами объекта. Например, следующая строка кода
a.rloc = 0;
не может находиться в функции main() предыдущей программы, потому что rloc является частным членом.

ЗАМЕТКА: Согласно существующему соглашению, в большинстве программ на языке С функция main() является первой функцией программы. Однако в програм­ме queue функции члены класса queue определены раньше функции main(). Такой подход является обычным при написании программ на языке C++.