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

Віртуальні функції

Читайте также:
  1. II. Основні напрями роботи, завдання та функції управління
  2. Аварійний комісар: поняття, функції.
  3. Адміністративна відповідальність: поняття, мета, функції, принципи та ознаки.
  4. Адміністративна служба, її завдання, функції.
  5. АРХІВНІ ДОВІДНИКИ В СИСТЕМІ НДА: ФУНКЦІЇ ТА СТРУКТУРА
  6. АТФ: хімічний склад і функції
  7. Б)Будова та функції нервово-м’язового синапсу. Механізм поєднання збудження та скорочення у м’язових волокнах.
  8. Будова і функції клітинних мембран. Транспорт речовин через мембрану.
  9. Будова та функції кишечника
  10. Вбудовані елементарні математичні функції
  11. Вбудовані функції. Основні поняття
  12. Види і функції соціальних інститутів

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

У C++ поліморфна функція прив'язується до однієї з можливих одноіменних функцій тільки у момент виконання, коли їй передається конкретний об'єкт класу. Іншими словами, виклик функції в початковому тексті програми лише позначається, без точної вказівки на те, яка саме функція викликається. Такий процес відомий як пізнє скріплення. Лістинг 3.9 показує, до чого може привести не поліморфну поведінку звичайних функцій-членів.

I class Parent { public:

double FI(double x) { return x*x; }

double F2(double x) { return FI(x) /2; }

 

class Child: public Parent { public:

double FI(double x) { return x*x*x; }};

 

void main() {

Child child;

cout “ child.F2(3) “ end1;

}

Лістинг 3.9. Невизначене пізнє скріплення.

Клас Parent містить функції-члени F1 і F2, причому, F2 викликає E1. Клас Child, похідний від класу Parent, успадковує функцію F2, проте перевизначає функцію F1. Замість очікуваного результату 13.5 програма видасть значення 4.5. Річ у тому, що компілятор відтранслюватиме вираз child. F2 (3) в звернення до успадкованої функції Parent::F2, яка у свою чергу викличе Parent::F1, а не Child::F1, що підтримало б поліморфну поведінку.

C++ однозначно визначає пізнє скріплення у момент виконання і забезпечує поліморфну поведінку функцій за допомогою їх віртуалізації. Лістинг 3.10 узагальнює синтаксис оголошення віртуальних функцій в базовому і похідному класах.

jclass classNamel {

// Інші функції-члени

virtual returnType functionName(<список параметрів>);

};

 

class className2: public classNamel {

// Інші функції-члени

virtual returnType functionName(<cписок параметрів>);

};

Лістинг 3.10. Оголошення віртуальних функції в ієрархії класів.

Щоб забезпечити поліморфну поведінку функції F1 в об'єктах класів Parent і Child, необхідно оголосити її віртуальною. Лістинг 3.11 містить модифікований текст програми.

class Parent {

public:

virtual double F1(double x) { return x*x; }

double F2(double x) { return Fl(x) /2; }

};

 

class Child: public Parent { public:

virtual double F1(double x) { return x*x*x; }

);

 

void main() {

Child child;

cout “ child.F2(3) “ endl;

}

Лістинг 3.11. Пізнє скріплення віртуальних функцій.

Тепер програма видасть очікуваний результат 13.5. Компілятор відтранслюватиме вираз child. F2 (3) в звернення до успадкованої функції Parent:: F2, яка у свою чергу викличе перевизначену віртуальну функцію нащадка Child::F1.

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

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

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

Дружні функції

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

class className

(1

public: ~

className(); // Конструктор за умовчанням // Інші конструктори friend returnType friendFunction(<список параметрів>);

};

Лістинг 3.12. Оголошення дружніх функцій.

Якщо звичайні функції-члени мають автоматичний доступ до всіх даних свого класу за рахунок передачі прихованого параметра - покажчика this на екземпляр класу, то дружні функції вимагають явної специфікації цього параметра. Дійсно, оголошена в класі Х дружня функція F не належить цьому класу, а, отже, не може бути викликана операторами х. F і xptr->F (де х- екземпляр класу X, а xptr- його покажчик). Синтаксично коректними будуть звернення F (& х) або F (xpt r).

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

3.6 Нові можливості мови C++

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

Важливо зрозуміти, що розширення мови ніколи не є самоціллю, і ви як і раніше зможете компілювати тексти, написані в рамках стандартного C++. Проте, щоб скористатися повною мірою перевагами, які надає C++Builder для технології швидкої розробки додатків (RAD), вам доведеться прийняти введені розширення мови.

Деякі з розширень (наприклад _ classid) C++Builder резервує, головним чином, для внутрішнього використання. Інші розширення абсолютно очевидні (_ int8, _intl6 і так далі), і тут не розглядаються. Нашу увагу буде сфокусовано на найбільш значущих розширеннях C++, які, в основному, відносяться до компонентних класів і постійно зустрічатимуться як в тексті книги, так і у ваших застосуваннях, що розробляються в середовищі C++Builder.

Компоненти

Компоненти часто досягають вищого ступеня інкапсуляції, ніж стандартні класи C++. Проілюструємо це на простому прикладі розробки діалогу, що містить кнопку. У типовій програмі C++ для Windows натиснення мишею на кнопку приводить до генерації повідомлення WM_IBUTTONDOWN. Це повідомлення повинне бути "зловлене" програмою або в операторові switch або у відповідному рядку таблиці відгуків (RESPONSE_TABLE), а потім передано процедурі реакції на це повідомлення. Так, додаток, написаний в рамках OWL (Object Windows Library), використовує макрос

DEFINE_RESPONSE_TABLE1(TEventTestDlgClient, TDialog)

//({TEventTestDlgClientRSP_TBL_BEGIN}}

EV_BN_CLICKED(IDEVENTBUTTON, EventBNClicked)

//({TEventTestDlgClientRSP_TBL_END}}

END_RESPONSE_TABLE;

щоб асоціювати подію (повідомлення WM_IBUTTONDOWN), що генерується кнопкою IDEVENTBUTTON в діалозі TEventTestDlgClient, з функцією реакції EventBNClicked.

C++Builder закінчив з цими важко освоюваними трюками програмістів. Компонент кнопки вже запрограмований так, щоб реагувати на натиснення кнопки подією OnClick. Все, що треба зробити - це вибрати готовий (або написати власний) метод і за допомогою Інспектора об'єктів включити його обробник даної події.


1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |

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



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