Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Курс лекцій.doc
Скачиваний:
15
Добавлен:
03.11.2018
Размер:
1.12 Mб
Скачать

2.3 Опис протоколу класу.

Розглянемо нові типи даних, що задаються за допомогою ключового слова class. Опис класу майже нічим не відрізняється від опису структури. У прикладі з структурою Ttime ми могли б описати аналогічний клас Ttime:

class TTime {

private:

int year;

int month;

int day;

int hour;

int minute;

public:

void Display (void);

};

void TTime::Display (void)

{printf ("year=%d month=%d day=%d hour=%d \

minute=%d \n", p--> year, p--> month, p--> day,\

p--> hour ,p--> minute);}

Схематично опис класу можемо задати наступним чином:

class Ім’я_Класу

{ private:

тип ідентифікатор;

. . . . . . . . . . . . . . . . . . .

тип ідентифікатор;

тип Ім’я_Функції 11(сигнатура);

. . . . . . . . . . . . . . . . . . .

тип Ім’я_Функції 1N1(сигнатура);

protected:

тип ідентифікатор;

. . . . . . . . . . . . . . . . . . .

тип ідентифікатор;

типрезультату Ім’я_Функції21(сигнатура);

. . . . . . . . . . . . . . . . . . .

типрезультату Ім’я_Функції2N2(сигнатура);

public:

тип ідентифікатор;

. . . . . . . . . . . . . . . . . . .

тип ідентифікатор;

типрезультату Ім’я_Функції 31(сигнатура);

. . . . . . . . . . . . . . . . . . .

типрезультату Ім’я_Функції 3N3(сигнатура);

Ім’я_Класу(сигнатура А);

Ім’я_Класу (сигнатура Б)

{ тіло функції }

~ Ім’я_Класу(void);

};

типрезультату Ім’я_Класу:: Ім’я_Функції 11(сигнатура)

{ тіло функції}

типрезультату Ім’я_Класу:: Ім’я_Функції 12(сигнатура)

{тіло функції}

. . . . . . . . . . . . . . . . . . . . . . . . . . .

типрезультату Ім’я_Класу:: Ім’я_Функції 3N3(сигнатура)

{тіло функції}

Ім’я_Класу ::Ім’я_Класу(сигнатура А)

{тіло функції}

Ім’я_Класу (сигнатура Б)

{ тіло функції }

Ім’я_Класу :~ Ім’я_Класу(void)

{ тіло функції }

Всі програмні компоненти, що містяться між відкриваючою та закриваючою фігурними дужками опису класу (“{“ - ”};”) утворюють формальний опис класу. Під протоколом класу будемо розуміти область, що складається з області формального опису класу та тіл функцій-членів, визначених за межами формального опису класу при допомозі операції розширення області видимості.

Бачимо, що формальний опис класу ділиться на три роздiли , що задаються за допомогою ключових слів private, protected та public. Кожен з цих розділів може мiстити поля даних та функцiї-члени. Порядок слідування роздiлiв та їх кiлькiсть можуть бути довiльними. Кількість полів у кожному розділі та порядок їх розміщення також може бути довільним. Якщо ключове слово вiдсутнє , то поля даних i функцiї-члени в цiй частинi опису класу вважаються закритими (для структур -вiдкритими ).

Як бачимо з схеми опису класу, крім “звичайних “ функцій-членів класи можуть мати функції, імена яких співпадають з іменем класу або утворюються по схемі: ~ Ім’я_Класу.Це так звані конструктори та деструктори.

Конструктор - це функцiя-член, iм'я якої спiвпадає з iменем класу. Конструктор може мати порожнiй список параметрiв. Допускаються параметри по замовчуванню, перегрузка. Ціль конструкторів - ініціалізація полів об’єкту (екземпляракласу). Присутність конструктора в протоколі класу не є обов’язковою.

Деструктор - це функція, ім’я якої ~ Ім’я_Класу . Деструктор повинен обов’язково мати порожнiй список параметрiв. В класі може бути не більше одного деструктора. Ціль деструктора - проведення корректних операцій при знищенні екземпляра класу (наприклад, звільнення пам’яті).

Конструктори i деструктори, так само як i iншi функцiї-члени можуть бути визначеними за межами формального опису класу. Якщо визначення функцiї включається в межі формального опису класу, то така функцiя розглядається компілятором як inline -функцiя. Діє правило: будь-яка змінна та функція є доступною в межах протоколу класу. Тобто в межах протоколу класу можна вільно звертатись до будь-якої змінної чи функції, описаної в цьому ж протоколі (так, ніби вони знаходяться в одному складеному операторі). Наприклад, в функції void TTime::Display (void) вільно використовуються поля month, hour та ін. без будь-яких додаткових описів. Що ж стосується доступу до полів ззовні протоколу (випадок коли вже визначений певний об’єкт-екземпляр класу), то прямий доступ можливий лише до полів даних та функцій -членів відкритого розділу (аналогічно, як вже розглядалось стосовно структур). Доступ до полів закритого та захищеного розділів здійснюється лише через функції-члени, що містяться у відкритих розділах.

Як вже відмічалось, обмеженість доступу до полів даних класу має ряд переваг:

а) перший етап вiдладки програми , - локалiзацiя помилки -, виконується ще до запуску програми за рахунок її органiзацiї . Адже помилка, пов’язана з використанням закритих даних, може виникнути лише в функції ( описаній у відкритому розділі), що працює з цими даними.

б) для того, щоб працювати з об’єктами, користувач не обов'язково повинен знати структуру закритих даних. Достатньо лише знати функцiї, якi працюють з цими даними.

в) легко можна змiнювати закриту частину даних без змiни основної програми.

Специфіка захищеного розділу буде розглянута пізніше.

Для ілюстрації пункту б) розглянемо, наприклад , ввід-вивід в С++ (детально він буде розглянутий пізніше). В систему С++ включаються класи ostream та istream. Вивiд iнформацiї здiйснюється шляхом передачi об'єкту cout класу ostream повiдомлення, яке виводиться. Наприклад, якщо хочемо надрукувати рядок " a string", в С++ можемо зробити це так:

cout << " a string\n";

Об'єкту cout можуть передаватись множиннi повiдомлення.

cout <<“ The values i ="<<i<<"\n";

Допускається при цьому форматований вивiд за допомогою функцiї form , параметри якої аналогічні параметрам функції printf:

cout<< form( “ i=%d”,i);

Для вводу потрiбно здiйснити передачу об'єкту cin класу istream повiдомлення iз змiнною, яка приймає данi, що вводяться, в якостi параматра. Аналогічно здійснюється форматований ввiд:

cin>> form( “ i=%d”,&i);

Взагалі, система вводу-виводу С++ є дуже складною. Класи вводу-виводу утворюють складну ієрархію, кожен клас ієрархії має свої функції та поля даних. Проте , користувач може взагалі не знати всієї цієї внутрішньої організації . Достатньо знати лише, яким об’єктам і як передаються відповідні повідомлення. Навіть з кількох наведених вище прикладів та короткої інформації ми формально можемо навчитись вводити та виводити дані в С++ (у найпростіших випадках). При цьому, поки що, для нас залишається незрозумілим, чому саме так і як все відбувається на внутрішньому рівні.