АвтоАвтоматизацияАрхитектураАстрономияАудитБиологияБухгалтерияВоенное делоГенетикаГеографияГеологияГосударствоДомДругоеЖурналистика и СМИИзобретательствоИностранные языкиИнформатикаИскусствоИсторияКомпьютерыКулинарияКультураЛексикологияЛитератураЛогикаМаркетингМатематикаМашиностроениеМедицинаМенеджментМеталлы и СваркаМеханикаМузыкаНаселениеОбразованиеОхрана безопасности жизниОхрана ТрудаПедагогикаПолитикаПравоПриборостроениеПрограммированиеПроизводствоПромышленностьПсихологияРадиоРегилияСвязьСоциологияСпортСтандартизацияСтроительствоТехнологииТорговляТуризмФизикаФизиологияФилософияФинансыХимияХозяйствоЦеннообразованиеЧерчениеЭкологияЭконометрикаЭкономикаЭлектроникаЮриспунденкция

АБСТРАКТНІ КЛАСИ І ЧИСТІ ВІРТУАЛЬНІ ФУНКЦІЇ_________________________________________

Читайте также:
  1. Академічний (класичний) період
  2. Аксіома про потенційну небезпеку. Класифікація небезпек
  3. Банківська система: сутність, принципи побудови та функції. особливості побудови банківської системи в Україн
  4. Бюджетно-податкова політика забезпечує найважливіші економічні функції держави, які формують її дієздатність в економічній політиці:
  5. Види податків і податкових платежів та їх класифікація
  6. Визначення величини резерва сумнівних боргів на основі класифікації дебіторської заборгованості
  7. Визначення групи кредитних операцій за станом обслуговування позичальником боргу за ними. Класифікація кредитного портфеля
  8. Визначення основних термінів статистики відходів. Класифікатор відходів
  9. Випадкові події. Класифікація подій
  10. Висвітлить класичний етап в розвитку соціології – 15 б.
  11. Витрати на інвестиції. Валові та чисті інвестиції
Давайте повернемося до класу shapeз програми Multshap. Ми ніколи не почнемо створювати об’єкт з класу shape, хіба що накреслимо декілька геометричних фігур – кругів, трикутників і тому подібне.
     

Базовий клас, об’єкти якого ніколи не будуть реалізовані, називається абстрактним класом. Такий клас може існувати з єдиною метою – бути батьківським по відношенню до похідних класів, об’єкти яких будуть реалізовані. Ще він може служити ланкою для створення ієрархічної структури класів.

Як нам пояснити людям, що використовують створену нами структуру класів, що об’єкти батьківського класу не призначені для реалізації? Можна, звичайно, заявити про це в документації, але це ніяк не захистить наш базовий клас від використання не за призначенням. Треба захистити його програмно. Для цього досить ввести в клас хоч би одну чисту віртуальну функцію.
     

Чиста віртуальна функція – це функція, після оголошення якої доданий вираз = 0.

Синтаксис:

virtual тип назва_функції (список_форм._параметрів)=0;

Чиста віртуальна функція нічого не робить і недоступна для виклику. Її призначення – служити основою для функцій, що підміняють її, в похідних класах. Абстрактний клас може використовуватися тільки як базовий для похідних класів.

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

Приклад. 21.3.

Class Base {

public:

Base(); // конструктор за замовчуванням

Base(const Base&); // конструктор копіювання

virtual ~Base(); // віртуальний деструктор

virtual void Show()=0; // чиста віртуальна функція

// інші чисті віртуальні функції

protected: // захищені члени класу

private:

// часто залишається порожнім, інакше заважатиме майбутнім розробкам

};

class Derived: virtual public Base {

public:

Derived(); // конструктор за замовчуванням

Derived(const Derived&); // конструктор копіювання

Derived(параметри); // конструктор з параметрами

virtual ~Derived(); // віртуальний деструктор

void Show(); // перевизначена віртуальна функція

// інші перевизначені віртуальні функції

protected:

// використовується замість private, якщо очікується наслідування

private:

// використовується для деталей реалізації

};

Об’єкт абстрактного класу не може бути формальним параметром функції, проте формальним параметром може бути вказівник на абстрактний клас. В цьому випадку з’являється можливість передавати у функцію, що викликається, як фактичний параметр значення вказівника на похідний об’єкт, замінюючи ним вказівник на абстрактний базовий клас. Таким чином ми отримуємо поліморфні об’єкти.

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

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

Наприклад, для геометричних фігур ми можемо визначити метод Draw, який їх малює: трикутник Ttriangle, коло Tcircle, квадрат Tsquare. Ми визначимо аналогічний метод і для абстрактного батьківського класу TgraphObject.Проте такий метод не може виконувати корисну роботу, оскільки в класі TgraphObject просто немає достатньої інформації для малювання чого б то не було. Проте присутність методу Draw дозволяє зв’язати функціональність (малювання) тільки один раз з класом TgraphObject, а не вводити три незалежні концепції для підкласів Ttriangle, Tcircle, Tsquare.
     

Є і друга, актуальніша причина використання абстрактного методу. У об’єктно-орієнтованих мовах програмування із статичними типами даних, до яких відноситься і С++, програміст може викликати метод класу, тільки якщо компілятор може визначити, що клас дійсно має такий метод.

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

Продемонструємо приклад VirtPure:

Лістинг 21.4. Програма VirtPure:

#include <iostream> using namespace std; Class Base // базовий клас { Public: virtual void show () = 0 // чиста віртуальна функція }; Class Derv1: public Base // похідний клас 1 { Public: void show () { cout <<? Derv1 \n?; } }; Class Derv2: public Base // похідний клас 2 { Public: void show () { cout <<? Derv2 \n?; } }; int main() { // Base bad // неможливо створити об’єкт Base* arr[2]; // масив вказівників на базовий клас Derv1 dv1; // об’єкт похідного класу Derv1 dv1; arr[0] = &dv1; //Занести адрес dv1 в масив arr[1] = &dv2; arr [0] = -> show(); // виконати функцію show() arr [1] = -> show(); // над двома об’єктами return 0; }
Тут віртуальна функція show() оголошується так: virtual void() show() = 0; //чиста віртуальна функція Знак рівності не має нічого загального з операцією привласнення. Нульове значення нічому не привласнюється. Конструкція = 0 – це просто спосіб повідомити компілятор, що функція буде чистою віртуальною. Якщо тепер в main() спробувати створити об’єкт класу Base, то компілятор буде незадоволений тим, що об’єкт абстрактного класу намагаються реалізувати. Він видасть навіть ім’я чистої віртуальної функції, яка робить клас абстрактним. Пам’ятаєте, що хоча це тільки оголошення, але визначення функції show() базового класу не є обов’язковим. Втім, якщо вам треба його написати, це можна зробити. Як тільки в базовому класі опиниться чиста віртуальна функція, необхідно буде поклопотатися про те, щоб уникнути це вживання у всіх похідних класах, які ви збираєтеся реалізувати. Якщо клас використовує чисту віртуальну функцію, він сам стає абстрактним, ніякі об’єкти з нього реалізувати не вдасться (похідні від нього класи, втім, вже не мають цього обмеження). Більш з естетичних міркувань, ніж з яких-небудь інших, можна всі віртуальні функції базового класу зробити чистими. Між іншим, ми внесли ще одну, не пов’язану з попередніми, зміну в VirtualPure: тепер адреси методів зберігаються в масиві вказівників і доступні як елементи цього масиву. Обробка цього, втім, нічим не відрізняється від використання єдиного вказівника. Virtualpureвидає результат, що не відрізняється від VIRT; Derv1 Derv2
     

 


1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |

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



Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Студалл.Орг (0.006 сек.)