Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лекції_ІЗВП_укр.doc
Скачиваний:
0
Добавлен:
01.04.2025
Размер:
6.39 Mб
Скачать

2. Оголошення або специфікація класу

Оголошення класу (class declaration) являє собою опис членів класу: даних і методів. Часто оголошення класу називають специфікацією. Члени-дані оголошуються згідно з правилами оголошення змінних і можуть мати будь-який тип, включаючи тип класу і покажчика на тип класу. Функції-члени в специфікації представлені прототипами.

Специфікація класу, як правило, розміщується в окремому заголовному файлі з розширенням .h і має наступний формат:

class ім’я_класy {

private:

/ / Закриті члени класу protected:

/ / Захищені члени класу

public:

/ / Відкриті члени класу

};

Оголошення класу починається з ключового слова class, за яким слідує ім'я класу, і закінчується крапкою з комою. Усередині фігурних дужок може знаходитися будь-яку кількість секцій зі специфікатор доступу, причому специфікатор можуть повторюватися (лістинг 14.1).

 Примітка

Якщо після відкриваючої фігурної дужки не стоїть ніякої специфікатор доступу, члени класу за замовчуванням стають private (закритими).

Лістинг програми - Приклад оголошення класу

/ / Book.h - специфікація класу Своок

 # Pragma once

class СВоок {

private:

char m_author [50]; / / автор

char * m_pTitle; / / покажчик на назву

int m_year; / / рік видання

public:

/ / Методи установки значень

void setAuthor (const char *);

void setTitle (const char *);

void setYear (const int);

/ / Методи повернення значень

 char * getAuthor (void);

char * getTitle (void);

 int getYear (void);

};

Файл специфікації Book.h містить оголошення типу класу CBоок. Щоб компілятор включав оголошення типу тільки один раз при трансляції програми, використовується директива препроцесора # pragma once.

У класі оголошені закриті дані з типом масиву m_author, покажчика на символьний тип m_pTitle і цілого m_уеаг, які описують автора, назву і рік видання, відповідно. Тип своок повідомляє компілятору, що для створення об'єкта типу CBоок потрібно 50 байтів для зберігання автора, 4 байти для адреси, за якою буде записано назву книги, і 4 байта для зберігання року видання.

Щоб можна було змінювати значення даних у об'єктів класу і отримувати ці значення в програмі, в класі оголошені відкриті методи. Функції - члени з типом значення, що повертається void мають параметр, тип якого відповідає типу даного. Методи для повернення значень не потребують параметрах, оскільки змінні, значення яких вони повертають, відомі класу. Тип кожного методу обумовлений типом повертаної (возвращаемой переменной) змінної.

3. Реалізація класу

Визначення оголошених в специфікації класу методів розташовується в окремому файлі з розширенням. срр, званому файлом реалізації класу.

Коли файли специфікації і реалізації класу знаходяться в різних файлах, заголовок функції-члена повинен включати область видимості згідно формату:

тип_функції-члена ім’я_класy :: ім’я_функції-члена (список параметрів)

Оператор дозволу області видимості :: використовується в заголовку з тією метою, щоб всі оголошені усередині класу ідентифікатори оброблялися усередині їхнього власного простору імен, а також щоб уникнути неоднозначності використання імен. Запис тіла методу нічим не відрізняється від запису в звичайній функції. У файл реалізації класу слід включити файл зі специфікацією класу, а також необхідні при визначенні функцій заголовки стандартних бібліотек (лістинг 14.2).

Листинг 14.2. Пример реализации класса

// Воок.срр - реализация класса СВооk

#include "Book.h"

#include <string>

// установить автора

void СВоок :: setAuthor ( const char* author ) {

strncpy_s < m_author, 50, author, 49 ) ;

if ( strlen ( author ) > 49 ) m_author [ 49 ] = ‘\0' ;

}

// установить название

void СВоок :: setTitle ( const char* title ) {

delete [ ] m_pTitle ;

m_pTitle = new char [strlen ( title )+ 1] ;

strcpy_s ( m_pTitle, strlen ( title ) + 1, title ) ;

}

// установить год издания

void СВоок :: setYear ( const int year )

{ m_уеаr = year ; }

// вернуть автора

char* СВоок :: getAuthor ( void )

{

return m_author ;

}

// вернуть название

char* СВоок :: getTitle ( void )

{

return m_pTitle ;

}

// вернуть год издания

int СВоок :: getYear ( void )

{

return m_year ;

}

Методи, показані в лістингу 14.2, не потребують особливих коментарів. Слід звернути увагу на визначення методів для встановлення значення автора і значення назви книги.

У методі setAuthor () в змінну m_author можна скопіювати тільки 49 байтів з параметра author. У разі перевищення цього значення залишок рядка author втрачається, і в останній байт масиву m_author записується нульовий байт.

У методі setTitle () дане m_pTitle є покажчиком, тому спочатку необхідно звільнити пам'ять, займану існуючим значенням на ¬ звання книги, виділити достатній для розміщення нової назви книги блок пам'яті і тільки потім копіювати значення параметра title. При виділенні пам'яті до довжини рядка title додається 1 байт для запису нульового байта.

Оголошення об'єкта класу

Оголошення об'єкта класу (object definition) не варто плутати з оголошенням класу. Важливо розуміти, що клас не містить ніяких значень даних, а лише описує загальну структуру і поведінку об'єктів, будучи як би трафаретом для їх створення.

Опис об'єкту задає його тип (ім'я класу) і, можливо, необхідні для ініціалізації членів-даних значення. При оголошенні об'єкта компілятор отримує вказівку на створення змінної класу на підставі заданого типу.

Коли об'єкт оголошується, то згідно з описом класу для об'єкта відбувається виділення оперативної пам'яті, а також при вказівці значень даних здійснюється ініціалізація членів-даних зазначеними значеннями. Всю цю роботу робить спеціальний метод класу, званий конструктором. Конструктори розглядаються в книзі в окремому розділі з однойменною назвою.

Основними форматами оголошення об'єкта класу є наступні:

имя_класса имя_объекта ;

имя_класса имя_объекта ( список параметров ) ; имя_класса имя_объекта ( имя_объекта_копирования ) ;

Листинг 14.3. Пример объявлений объектов класса

CBook book, аВооk [ 100 ] ;

СВоок obj ( "Carrol L.", "Alice in Wonderland", 2002 ) ;

CBook copy ( obj ) ;

У лістингу 14.3 використані всі три формату для оголошення об'єктів типу класу CBоок. Згідно з першим, оголошується об'єкт book і масив з 100 об'єк ¬ тів аВоок. За другим формату оголошений об'єкт obj, і по третьому - об'єк ¬ ект сміттю.

Конструктори

При створенні чергового екземпляра класу часто виникає необхідність початкової ініціалізації деяких змінних. Для цієї мети і служить конструктор. При створенні екземпляра класу автоматично викликається конструктор. Ім'я функції конструктора завжди збігається з ім'ям класу. Нижче представлені код оголошення та реалізації конструктора класу CMyClass.

Бувають так само й такі ситуації, коли для правильної початкової ініціалізації необхідна деяка вхідна інформація. Для цієї мети служать конструктори з параметрами. Параметрів у конструкторі може бути скільки завгодно. Нижче представлений приклад використання конструктора з одним цілочисловим параметром для ініціалізації змінної класу.

Треба сказати, що конструкторів у класі може бути декілька, і використовувати можна той, який найбільше підходить для тієї чи іншої ситуації. Наведу приклад:

Деструктори

Деструктори - функції, які виконують де ініціалізацію елементів класу. Навіщо це потрібно? Наведу приклад. Уявіть собі, що в класі є кілька ініціалізованних покажчиків. Якщо видалити екземпляр класу просто так, то можливий витік пам'яті, тобто елементи класу в "купі" так і будуть висіти в ній до кінця виконання програми. Можна, звичайно, примудритися і кожен раз писати видалення елементів з "купи" вручну, але це довго, незручно, а саме головне не потрібно. Достатньо лише прописати рядки видалення в деструкції, який буде викликатися при видаленні кожного екземпляра класу. Деструктор також, як і конструктор носить ім'я класу, але перед ним йде знак "~". Наведу приклад деструктора класу CMyClass:

Останнє, що треба сказати про деструкцію, це те, що в одному класі не може бути більше одного деструктора. Варто напомнити ще про те, що не буває деструкторів з параметрами.

  1. Використання конструкторів та деструкторів у пакеті Visual C++

Конструктори класу

При створенні об'єкта автоматично викликається спеціальний метод, кото ¬ рий називається конструктором (constructor). У конструктора ім'я класу і обов'язково відкритий специфікатор доступу. Конструктор управляє по ¬ будовою об'єкта в оперативній пам'яті. Процес побудови включає в себе виділення пам'яті для членів-даних типу покажчиків, а також ініціалізацію даних.

Конструктор ніколи не повертає ніякого значення і не має типу, навіть void. Конструктор перевантажується, так як об'єкти можна ініціалізувати по-різному. Кількість конструкторів практично не обмежується і за ¬ висить від доцільності їх наявності в класі. Однак існують конструктори, без яких не обійтися жодному класу. Це конструктор за умовчанням, конструктор з параметрами і конструктор копіювання.

Важливо пам'ятати, ніякої конструктор не повинен робити нічого, що стосується обробки членів-даних. За обробку членів-даних несуть відповідальність не конструктори, а інші методи в класі.

Ініціалізатор в конструкторах

Головним завданням конструктора класу є ініціалізація даних створюваних їм об'єктів. Однак проводити ініціалізацію даних при помочі оператора присвоювання в тілі конструктора не рекомендується.

Ініціалізація здійснюється за допомогою списку ініціалізації, розташована між двокрапкою, яке слідує за закриваючою круглою дужкою в заголовку конструктора, і тілом конструктора. Привласнюються при ініціалізації даних значення записуються в круглих дужках після ідентифікаторів членів-даних і відокремлюються один від одного комами.

Порядок проходження ідентифікаторів у списку ініціалізації не має значення.

Конструктор за замовчуванням

Конструктор за замовчуванням - конструктор, який не потребує параметрів. Цей конструктор завжди повинен бути визначений для будь-якого класу. Конструктор за замовчуванням може не виконувати ніяких дій, але найчастіше він ініціалізує дані класу нульовими значеннями.

Оголошення конструктора за замовчуванням має наступний формат:

public: ім’я_класy ();

Конструктор з параметрами

Конструктор з параметрами ініціалізує значення даних об'єкта значень отриманих параметрів. Параметрів буде стільки, скільки даних необхідно проініциалізувати. Прототип такого конструктора має формат:

public:имя_класса ( список формальных параметров ) ;

Для класу CBооk конструктор з параметрами може мати наступний прототип: CBook ( char*, char*, int ) ;

Листинг 14.5 – Пример реализации конструктора с параметрами

CBook :: CBook ( char *author, char *title, int year )

: m_уеаr ( year ) , m_pTitle ( title )

{

strncpy_s ( m_author, 50, author, 49 ) ;

if ( strlen ( author ) > 49 ) m_author [ 49 ] = '\0' ;

}

В результаті роботи цього конструктора (лістинг 14.5) буде побудований об'єкт-книга, у якого дане m_уеаг отримає значення параметра year, в масив m_author буде скопійовано не більше 49 байтів з рядка author, і покажчик m_pTitle буде містити адресу, за якою скопійовано значення title.

Конструктор копіювання

Конструктор копіювання створює копію об'єкта в оперативній пам'яті за допомогою іншого об'єкта того ж класу. В якості параметра цей конструктор отримує посилання на об'єкт, копію якого необхідно створити. Для конструктора копіювання необхідно вказати прототип наступного формату:

public: ім’я_класy (ім’я_класy &);

Для класу CBооk конструктор копіювання оголошується в специфікації класу з наступним прототипом:

CBook (CBook &);

Лістинг 14.6. Приклад конструктора копіювання

CBook :: CBook ( CBook &o ) : m_year ( о.m_year ) {

strcpy_s ( m_author, strlen ( o.m_author ) + 1, o.m_author ) ;

nupTitle = new char [strlen ( o.m_pTitle ) + 1 ] ;

Strcpy_S ( m_pTitle, strlen ( O.m_pTitle ) + 1, O.m_pTitle ) ;

}

В результаті роботи конструктора копіювання (лістинг 14.6) буде будований новий об'єкт-книга, всі члени-дані якого отримають значення даних, які належать копійованому об'єкту, переданому по посиланню. Щоб привласнити значення назви книги знову створюваному об'єкту, потрібно спочатку виділити необхідний блок пам'яті за допомогою оператора new.

Деструктор

Деструктор (destructor) - спеціальний метод класу, використовуваний для руйнування об'єктів класу. Ім'я деструктора збігається з ім'ям конструктора (ім'ям класу), якому передує символ тильда Він завжди має відкритий специфікатор доступу і не має ні типу, ні параметрів. Деструктор управляє знищенням об'єкта з оперативної пам'яті.

Викликається деструктор автоматично при руйнуванні об'єкта. Якщо об'єкт створювався динамічно через покажчик за допомогою оператора new, то для знищення такого об'єкта слід використовувати оператор delete для покажчика.

Типовим використанням деструктора є звільнення динамічної пам'яті, яка раніше була виділена конструктором.

На відміну від конструктора, деструктор не перевантажується і може бути в класі тільки один. Краще завжди визначати деструктор класу, навіть якщо він не виробляє ніяких дій і має порожнє тіло.

Оголошення деструктора має наступний формат:

public: ~ ім’я_класy ();

Наприклад, для класу CBооk прототип деструктора в специфікації класу має вигляд:

~ CBook ();

Лістинг 14.7

CBook () :: ~ CBook ()

{Delete () m_pTitle;}

Результатом дії деструктора ~ CBook () є звільнення блоку пам'яті з початковим адресою з m_pTitle, виділеного раніше конструктором класу (лістинг 14.7).

Виклик конструктора і деструктора

Як згадувалося раніше, конструктор і деструктор викликаються в програмі автоматично при оголошенні об'єктів класу. Не має значення, чи оголошується об'єкт явно або створюється динамічно за допомогою new.

Виклик того чи іншого конструктора залежить від форми опису об'єкта:

• Якщо після імені об'єкта або типу класу в операторі new нічого не зазначено або стоять порожні круглі дужки, викличеться конструктор за замовчуванням.

• Якщо в дужках записані параметри, викликається конструктор з параметрами.

• Якщо в дужках знаходиться ім'я об'єкта, то відбувається виклик конструктора копіювання.

Деструктор також викликається автоматично, коли за допомогою оператора delete звільняється покажчик на об'єкт класу. Без оператора delete об'єкт зруйнований не буде. Дозволяється та явний виклик деструктора для об'єкта, який виконується, як і виклик будь-якого іншого методу класу.

Деструктори викликаються в порядку, зворотному порядку оголошення іменованих об'єктів у програмі. Виклик деструкторів об'єктів, оголошених через покажчики, визначається проходженням операторів delete для цих указників (лістинг 14.8).

Коли викликаються конструктори і деструктори

Якщо говорити загалом, конструктор викликається при створенні об'єкта, а деструктор - при його знищенні. У наступному списку детально перераховані випадки виклику конструкторів та деструкторів для різного виду об'єктів.

• Об'єкт визначений глобально (тобто поза будь-якої функції). Конструктор викликається на самому початку програми до виклику функції main (або WinMain в програмі, що працює в середовищі Windows), деструктор - по закінченні програми.

• Об'єкт визначений локально (тобто всередині функції). Конструктор викликається, коли потік управління досягає визначення об'єкта, деструктор - при виході за межі блоку, в якому визначено об'єкт (тобто коли об'єкт виходить з області видимості).

• Об'єкт визначений локально з використанням специфікатора static. Кон-структор викликається, коли потік управління вперше досягає визначення об'єкта, деструктор - в кінці програми;

• Об'єкт створений динамічно з використанням оператора new. Конструктор викликається при створенні об'єкта, а деструктор - коли об'єкт явно знищується з використанням оператора delete. Якщо цього не відбувається, деструктор не буде викликаний ніколи.