Знакомство с классами

Понятие класса

Инкапсуляция - механизм, позволяющий объединять в едином объекте множество его характеристик (данные, характеризующие объект) и действий над ними (средства обработки этих данных).

Сокрытие представляет собой принцип разграничения доступа различных частей программы к различным элементам данных и действий над ними.

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

Класс – это тип данных, определяемый пользователем. Класс может содержать определение только данных или только некоторых действий, но чаще всего он содержит и то, и другое.

Данные (переменные), характеризующие класс, называются членами данных, а действия над ними (функции) – функциями-членами класса.

Для работы с некоторым классом создаются переменные этого типа, называемые экземплярами класса.

Определение класса осуществляется с помощью инструкции class:

 

class <идентификатор класса>

{

// Закрытые члены класса

public:

// Открытые члены класса

} <список экземпляров класса>;

Например:

 

typedef double t_Inf; //Тип данных элементов массива

const t_Inf DefVal = 0; //Значение элемента массива по умолчанию

char Err [] = "\n***В массиве нет элемента с индексом "; //Сообщение об ошибке

class t_DinArr {

// Закрытые члены-данные класса

t_Inf * Arr; //Указатель на динамический массив

unsigned ItemCount; //Количество элементов в массиве

public:

// Открытые члены-функции класса

void Init (unsigned N = 0); //Инициализация массива из N элементов

void Clear(); //Очистка массива

void Set (unsigned Ind, t_Inf Val); //Запись значенияVal в элемент с индексом Ind

t_Inf Get (unsigned Ind); //Возвращает значение элемента с индексом Ind

void Add ( t_Inf Val ); //Добавляет в конец массива элемент со значением Val

unsigned Count (); //Возвращает количество элементов массива

void Free (); //Удаление массива из динамической памяти

} ;

 

В этом примере начато создание класса для работы с одномерными динамическими массивами. Элементами этого массива являются данные типа t_Inf (в этом примере – эквивалент типаdouble). Константа DefVal = 0 определяет значение элементов массива по умолчанию.

Идентификатор класса t_DinArr определяет новый пользовательский тип данных, включающий в себя два члена-данных: Arr(указатель на массив элементов типа t_Inf) и ItemCount (переменная, определяющая текущее количество элементов массива). И Arr и ItemCount являются закрытыми членами класса (все члены класса, расположенные до слова public, являются закрытыми). После слова public перечисляются открытые члены класса. В нашем примере это пять членов-функций. Функция Initсоздает динамический массив на N элементов и инициализирует его элементы значениямиDefVal. Функция Setприсваивает элементу массива с индексом Ind значение Val. Функция Get возвращает значение элемента массива с индексом Ind. Функция Countвозвращаетколичество элементов массива. Функция Free удаляет массив из динамической памяти. Члены-функции определяются с помощью прототипов. Реализация этих функций приведена ниже. Таким образом, класс инкапсулирует два члена-данных и пять функций членов.

Различие между закрытыми и открытыми членами класса состоит в следующем. К закрытым членам класса могут обращаться только другие члены класса (открытые и закрытые). Открытые члены класса доступны везде (и в других членах класса, и в программе). Иными словами, при использовании некоторого класса программист в программе может пользоваться только открытыми членами класса. Закрытые члены класса могут использоваться только внутри реализации класса. Определяя Arrи ItemCount закрытыми, мы осуществляем сокрытие этих данных от прямого доступа к ним. При использовании этого класса в программе программист не может напрямую изменять эти данные, что предотвращает возможность возникновения ошибок при работе с массивом. Например, если сделать Arr открытым членом класса, то в программе можно будет напрямую изменить значение указателя на первый элемент массива, присвоив ему, например, значение 0. В этом случае уже имеющийся в динамической области памяти массив будет «потерян» - произойдет утечка памяти. Этого допускать нельзя. То же самое касается и члена класса ItemCount – произвольные изменения его значения могут привести к неправильной работе программы.

Перейдем к реализации членов функций.

Член функцию Init можно реализовать так:

 

void t_DinArr :: Init (unsigned N) //Инициализация массива из N элементов

{

if (N) //ЕслиNбольше0

//Выделяем память в динамической области дляN элементов массива

Arr = (t_Inf *) malloc ( sizeof(t_Inf) * N );

Else

//ПриN = 0указатель на массив равен0 –массива нет

Arr = 0;

//Устанавливаем значение количества элементов в массиве

ItemCount = N;

//Очищаем массив значениями DefVal

Clear();

}

В чем особенности определения:

1. Для того, чтобы показать, что функцияInit является членом классаt_DinArr, перед ее именем необходимо указать префикс t_DinArr ::.

2. Обращение и к открытым, и к закрытым членам класса внутри тела функции осуществляется напрямую

Аналогичным образом реализуются и остальные функции члены класса:

 

void t_DinArr : : Clear () //Очистка массива значениями DefVal

{

for (unsigned i = 0; i < ItemCount; ++ i)

Arr [i] = DefVal;

}

//Запись значенияVal в элемент с индексом Ind

void t_DinArr : : Set(unsigned Ind, t_Inf Val)

{

if (Ind >= ItemCount) //Индекс выходит за границу массива

cout << Err << Ind << '!\n'; //Выводим сообщение об ошибке

else //Индекс правильный

Arr [Ind] = Val; //Элементу массива с индексом Ind присваиваем значениеVal

}

//Возвращает значение элемента с индексом Ind

t_Inf t_DinArr : : Get(unsigned Ind)

{

if ( Ind >= ItemCount ) //Индекс выходит за границу массива

{

cout << Err << Ind << "!\n"; //Выводим сообщение об ошибке

return DefVal; //Возвращаем из функции значениеDefVal

}

else //Индекс правильный

return Arr [ Ind ]; //Возвращаем из функции значение элемента с индексом Ind

}

 

//Добавляет в конец массива элемент со значением Val

void t_DinArr : : Add(t_Inf Val)

{

++ ItemCount; //Количество элементов в массиве увеличиваем на 1

//Увеличиваем размер массива до нового количества элементов

Arr = ( t_Inf * ) realloc ( Arr, sizeof(t_Inf) * ItemCount );

//В новый (последний) элемент массива записываем значениеVal

Arr [ ItemCount – 1 ] = Val;

}

unsigned t_DinArr : : Count ( ) //Возвращает количество элементов массива

{

Return ItemCount;

}

void t_DinArr : : Free ( ) //Удаление массива из динамической памяти

{

if (Arr) //Указатель на массив не равен0 –массив есть

{

free(Arr); //Освобождаем динамическую память

Arr = 0; //Делаем указатель на массив равным0 –массива нет

ItemCount = 0; //Присваиваем количеству элементов в массиве значение0

}

}

 

Первый вариант класса t_DinArr готов. Его использование иллюстрируется следующим примером:

 

Int main ( )

{

setlocale ( 0, "" );

//Описываем экземпляр класса (статическая переменная DA типа t_DinArr):

T_DinArr DA;

//Вводим с клавиатуры необходимый размер массива:

Unsigned N;

cout << “Количество элементов в массиве: ”;

cin >> N;

// Инициализируем экземпляр класса (при этом в динамической области

// памяти будет создан массив на заданное количество элементов

// и этот массив будет «обнулён» значениями DefVal):

DA.Init ( N );

// В цикле заполняем созданный массив некоторыми значениями, например,

// равными индексам элементов массива:

for ( unsigned i = 0; i < DA.Count ( ); ++ i )

DA.Set ( i, i );

// Для контроля выводим на экран значения элементов массива:

for ( unsigned i = 0; i < DA.Count ( ); ++ i )

cout << DA.Get ( i ) << ‘ ‘;// на экране видим числа:0 1 2 … N-1

cout << endl;

// В цикле добавляем в конец массива еще 5 элементов, информационные части

// которых заполняются значениями, от N до N + 4

for ( unsigned i = 0; i < 5; ++ i )

DA.Add ( N + i );

// Снова для контроля выводим на экран значения элементов массива:

for ( unsigned i = 0; i < DA.Count ( ); ++ i )

cout << DA.Get ( i ) << ‘ ‘;// на экране видим числа:0 1 2 … N + 4

cout << endl;

// Заканчиваем работу с массивом (освобождаем динамическую память):

DA.Free ( );

system ( "pause" );

Return 0;

}

 

Обсудим использование класса в этом примере.

  1. Обращение к членам экземпляра класса осуществляется точно так же, как и к полям обычных структур, с помощью оператора «точка», например: DA.Init ( N ).
  2. В функции main обращаться можно только к открытым членам класса. Доступ к закрытым членам класса (Arr и ItemCount) осуществляется опосредованно через функции члены класса, что защищает программу от случайных возможно ошибочных изменений этих данных.
  3. Для работы с массивом необходимо перед началом работы объявить экземпляр класса (t_DinArr DA;) и инициализировать его (DA.Init ( N );).
  4. При окончании работы с экземпляром класса необходимо освободить динамическую память (DA.Free ( );).

Рабочая программа этого примера приведена в Приложении 1.








Дата добавления: 2019-02-07; просмотров: 232;


Поиск по сайту:

При помощи поиска вы сможете найти нужную вам информацию.

Поделитесь с друзьями:

Если вам перенёс пользу информационный материал, или помог в учебе – поделитесь этим сайтом с друзьями и знакомыми.
helpiks.org - Хелпикс.Орг - 2014-2024 год. Материал сайта представляется для ознакомительного и учебного использования. | Поддержка
Генерация страницы за: 0.028 сек.