Конструктори і деструктори МІНІСТЕРСТВО ОСВІТИ І НАУКИ, МОЛОДІ ТА СПОРТУ УКРАЇНИ НАЦІОНАЛЬНИЙ УНІВЕРСИТЕТ “ЛЬВІВСЬКА ПОЛІТЕХНІКА” ОБ’ЄКТНО-ОРІЄНТОВАНЕ ПРОГРАМУВАННЯ МЕТОДИЧНІ ВКАЗІВКИ до виконання лабораторної роботи на тему: “Класи” для студентів базового напряму 6.050101 “Комп’ютерні науки” Затверджено на засіданні кафедри загальної екології та екоінформаційних систем Протокол № 13 від 24.05.2012 р. Львів – 2012 Об’єктно-орієнтоване програмування:Методичні вказівки до виконання лабораторної роботи на тему “Класи” для студентів базового напряму 6.050101 “Комп’ютерні науки” / Укл.: І. Я. Казимира, О. Н. Кузь. – Львів: Видавництво Національного університету “Львівська політехніка”, 2012. – 23с. Укладачі:Казимира І. Я., к.т.н., доц. Кузь О. Н., асист. Відповідальний за випуск:Заяць В. М., д.т.н., проф. Рецензенти:Яцимірський М. М., д.т.н., проф., Фармага І. В., к.т.н., доц. Теоретичні відомості Класи Терміном клас визначається тип об’єктів. При цьому кожен представник (чи екземпляр) класу називається об’єктом. Кожен об’єкт завжди має свій, унікальний стан, який визначається поточним значенням його даних-членів (елементів-даних). Функціональне призначення класу визначається можливими діями над об’єктами класу, які задаються його функціями-членами (функціями-елементами, або методами). Поняття класу є, напевно, найбільш важливим у мові С++. Синтаксис опису класу схожий на синтаксис опису структури. Це його основна форма: class <ім’я_класу> { //закриті функції-члени і дані-члени класу public: //відкриті функції-члени і дані-члени класу } <список_об’єктів>; В описі класу <список_об’єктів> не є обов’язковим. Ви можете оголосити об’єкти класу пізніше, по мірі необхідності. Так переважно і роблять. Хоча <ім’я_класу> також є не обов’язковим, проте його зазвичай вказують. <ім’я_класу> стає новим іменем типу даних, яке використовується для виявлення об’єктів цього класу. Функції і змінні, які оголошені всередині оголошення класу, стають членами цього класу. Змінні, оголошені всередині оголошення класу, називаються даними-членами цього класу; функції, оголошені всередині оголошення класу, називаються функціями-членами класу. По замовчуванню, всі функції і змінні, оголошені в класі, стають закритими для членів цього класу. Це означає, що вони доступні тільки для інших членів цього класу. Для оголошення відкритих членів класу використовують ключове слово public, за яким ставиться двокрапка. Всі функції і змінні, оголошені після слова public, доступні і для інших членів класу, і для будь-якої іншої частини програми, в якій міститься клас. Приклад оголошення класу: class AnyClass { //закриті елементи класу іnt a; public: int get_a(); void set_a(int num); }; Хоча функції get_a() і set_a() і оголошені в класі AnyClass, вони ще не визначені. Для визначення функцій-члена потрібно пов’язати ім’я класу, частиною якого виявляється функція-член, з ім’ям функції. Це досягається шляхом написання імені функції відразу після імені класу з двома двокрапками. Операцію, яку записують у вигляді двох двокрапок, називають операцією розширення області видимості. Для задання функції-члена використовується наступна загальна форма: <Тип> <ім’я_класу>::<ім’я_функції> (<список_параметрів>) { //тіло функції } Нижче наведені приклади визначення функцій-членів get_a() і set_a(): void AnyClass::get_a() { return a; } int AnyClass::set_a(int num) { a = num; } Оголошення класу AnyClass не приводить до створення об’єктів типу AnyClass. Щоб створити об’єкт відповідного класу, потрібно просто використати ім’я класу як специфікатор типу даних. Наприклад: AnyClass ob1, ob2; Після того як об’єкт класу створений, можна звертатись до відкритих членів класу, використовуючи операцію "крапка", так само як до полів структури. Наприклад: ob1.set_a(10); ob2.set_a(37); Ці оператори встановлюють значення змінної а в об’єктах ob1 і ob2. Кожен об’єкт містить власну копію всіх даних, які оголошені в класі. Це означає, що значення змінної а в ob1 відмінне від значення цієї змінної в ob2. Доступ до елементів даних класу можна отримати і з допомогою вказівника на об’єкт цього класу. Наступний приклад це показує. class Coord { public: int x,y; void SetCoord(int_x, int_y); }; void Coord::SetCoord(int_x, int_y) { x = _x; y = _y; } int main() { Coord pt; Coord *ptPtr = &pt; //вказівник на об’єкт //... pt.x = 0;//обєкт.член_класу ptPtr->y = 0;//вказівник->член_класу ptPtr->SetCoord(10,20); //... return 0; } Серед програмістів часто виникає дискусія про те, який метод доступу до членів класу – через оператор "." чи через оператор "->" – працює швидше. Розглянемо це питання. Оператор вибору члена “.” працює так само, як і оператор “->”, проте відмінність полягає в тому, що перед ім’ям об’єкту є неявно згенерований компілятором оператор адреси “&”. Таким чином, інструкцію ObjName.FuncName(); компілятор трактує, як (&ObjName)->FuncName(); Імена елементів класу можуть так само використовуватись з іменем класу, за яким пишуть операцію розширення видимості (подвійна двокрапка), тобто виклик елемента має вигляд: <ім’я_класу>::<ім’я_члена> Мова С++ накладає певні обмеження на дані-члени класу: · дані-члени не можуть визначатись з модифікаторами auto, extren чи register; · даним-членам класу не може бути об’єкт цього ж класу (проте даним-членом може бути вказівник або посилання на об’єкт цього класу, чи сам об’єкт іншого класу). Імена всіх елементів класу (даних і функцій) мають своєю областю дії цей клас. Це означає, що функції-члени можуть звертатись до будь-якого елемента класу просто по імені. Клас повинен бути оголошений до використання його членів. Проте інколи в класі повинен бути оголошений вказівник чи посилання на об’єкт іншого класу ще до того, як він визначений. В цьому випадку необхідно звертатись до неповного оголошення класу так: class <ім’я_класу>; Розглянемо наступний приклад. //Неповне оголошення класу class PrevDecl; class AnyClass { int x; PrevDecl* obPtr; public: Any Class(int_x){x = _x;} }; int main() { //тіло основного блоку return 0; } //Повне оголошення класу class PrevDecl { int a; public: PrevDecl(); }; Не можна створити об’єкт не повністю визначеного класу. Спроба створення такого класу приведе до помилки компіляції. Зауважимо, що визначення класу нагадує визначення структури, за винятком того, що визначення класу: · зазвичай містить один або декілька специфікаторів доступу, які задаються за допомогою ключових слів public, protected чи private; · замість ключового слова struct можуть використовуватись class чи union; · зазвичай містить поряд з елементами даних фунції-члени; · зазвичай містить деякі спеціальні функції-члени, такі як конструктор і деструктор. Нижче наведені приклади визначення класів з використанням ключових слів struct i union. struct Point { private: int x; int y; public: int GetX(); int GetY(); void SetX(int_x); void SetY(int_y); }; union Bits { Bits(unsigned int n); void ShowBits(); unsigned int num; unsigned char c[sizeof(unsigned int)]; }; Специфікатор доступу застосовується до всіх елементів класу, які йдуть за ним, поки не зустрінеться інший специфікатор доступу чи не закінчиться визначення класу. Таблиця 1 описує три специфікатори доступу Таблиця 1 Специфікатори доступу до класу Специфікатор | Опис | private: | Дані-члени і функції-члени доступні тільки для функцій-членів цього класу | protected: | Дані-члени і функції-члени доступні для функцій-членів даного класу і класів, які є похідними від нього | public: | Дані-члени і функції-члени класу доступні для функцій-членів цього класу та інших функцій програми, в якій є представник класу | В С++ клас, структура і об’єднання розглядаються як типи класів. Структура і клас схожі один на одного, за винятком доступу по замовчуванню: в структурі елементи мають по замовчуванню доступ public, а клас private. Об’єднання, як і структура, по замовчуванню має доступ public. В наведеній нижче таблиці 2 наведені ці відмінності. Таблиця 2 Відмінності між класом, структурою та об’єднанням Відмінності | Класи | Структури | Об’єднання | Ключове слово: | class | struct | union | Доступ по замовчуванню: | private | public | public | Перекриття даних: | ні | ні | так | Структури і об’єднання можуть мати конструктори і деструктори. Поряд з цим є декілька обмежень на використання об’єднань в якості класів. По-перше, вони не можуть успадковувати будь-який клас, і вони самі не можуть використовуватись в якості базового класу для будь-якого іншого типу. Загалом, об’єднання не підтримують ієрархію класів. Об’єднання не можуть мати членів с атрибутом static. Вони також не повинні містити об’єктів з конструктором і деструктором. Розглянемо приклад використання об’єднання в якості класу: #include <iostream.h> union Bits { Bits(unsigned int n); void ShowBits(); unsigned int num; unsigned char c[sizeof(unsigned int)]; }; Bits::Bits(unsigned int n) { num = n; } void Bits::ShowBits() { int i, j; for (j=sizeof(unsigned int)-1; j>=0; j--) { cout<<”Двійкове подання байта”<<j<< ”:”; for (i=128; i; i>>=1) { if (i & c[j]) cout <<”1”; else cout <<”0”; } cout<<”\n”; } } int main() { Bits ob(2000); ob.ShowBits(); return 0; } В цьому прикладі здійснюється побайтовий вивід переданого об’єкту беззнакового цілочисельного значення у двійковому вигляді. Конструктори і деструктори |