- •2.1 Елементи концепції ооп .. 20
- •1.1 Коментарі.
- •1.2 Прототипи функцій.
- •1.3 Операція розширення області видимості.
- •1.4 Оголошення в операторах.
- •1.5 Перегрузка функцій.
- •1.6 Значення формальних параметрів по замовчуванню.
- •1.7 Посилання та вказівники.
- •1.8 Специфікатор inline
- •1.9 Операції new та delete .
- •1.10 Вказівник на void.
- •1.11 Зв’язування із збереженням типів
- •1.12 Про структури та об’єднання.
- •2.1 Елементи концепції ооп.
- •2.3 Опис протоколу класу.
- •2.4 Передача повідомлень об’єктам.
- •3 Функції-члени.
- •3.1 Функції-члени в межах та за межами формального опису класу.
- •3.2 Про вказівник this.
- •3.3 Перевантаження функцій-членів. Параметри по замовчуванню.
- •4. Конструктори та деструктори.
- •4.1 Поняття про конструктори.
- •4.2 Деструктори.
- •4.3 Досягнення високої ефективності. Конструктор копіювання.
- •5 Глобальні та локальні об’єкти.
- •6 Статична пам’ять та класи.
- •7. Наслідування
- •7.1 Синтаксична реалізація наслідування
- •7.2 Правила доступу до полів даних
- •7.3 Конструктори та деструктори в похідних класах
- •7.4 Використання заміщуючих функцій-членів.
- •7.5 Похідні класи та вказівники.
- •7.6 Ієрархія типів
- •7.7 Множинне наслідування
- •8 Вiртуальнi функцiї та класи
- •8.1 Віртуальні функції.
- •8.2 Чисті віртуальні функції. Абстрактні класи.
- •8.3 Віртуальні деструктори.
- •8.4 Посилання як засіб для реалізації поліморфізму
- •8.5 Технічна реалізація механізму віртуальних функцій.
- •8.6 Віртуальні базові класи
- •8.6.1 Ієрархії класів та наслідування
- •8.6.2 Віртуальні базові класи
- •8.6.3 Виклик конструкторів та віртуальні базові класи.
- •9 Друзі
- •9.1 Дружні класи.
- •9.2 Дружні функції.
- •10 Перевантаження операторiв.
- •10.1 Перевантаження операторів. Загальний підхід.
- •10.2 Перетворення типів.
- •10.3 Перевантаження деяких операторів.
- •10.3.1 Оператор індексування масиву.
- •10.3.2 Перевантаження оператора виклику функції.
- •10.3.3 Оператор доступу до члена класу.
- •10.3.4 Перевантаження операторів інкремента та декремента.
- •10.3.5 Перевантаження операторів управління пам’яттю (new,delete).
- •10.3.6 Перевантаження оператора присвоювання.
- •11.1 Функціональні шаблони
- •11.1.1 Визначення та використання шаблонів функцiй.
- •11.1.2 Перевантаження шаблонiв функцiї.
- •11.1.3 Cпецiалiзованi функцiї шаблона.
- •11.2 Шаблони класів.
- •11.2.1 Визначення шаблонів класу
- •11.2.2 Константи та типи як параметри шаблону
- •11.2.3 Використання шаблонних класів
- •11.2.4 Спецiалiзацiя шаблонiв класу.
- •11.3 Шаблони та конфiгурацiя компiлятора.
- •11.3.1 Шаблони Smart.
- •11.3.2 Шаблони Global I External.
- •12.2 Переадресація вводу-виводу
- •12.3 Розширення потоків для типів кориcтувача
- •12.4 Операції роботи з потоком як дружні
- •12.5 Форматований ввід-вивід
- •12.5.1 Ширина поля
- •12.5.2 Заповнюючий символ
- •12.5.3 Число цифр дійсних чисел
- •12.5.4 Прапорці форматування
- •12.5.5 Маніпулятори
- •12.6 Стан потоку
- •12.7 Файловий ввід-вивід
- •12.7.1 Конструктори файлових потокiв
- •12.7.2 Вiдкриття файлу
- •12.8 Неформатований ввід-вивід
- •12.9 Деякі функції вводу-виводу
- •12.10 Форматування в пам’яті
- •13 Управління виключеннями
- •13.1 Виключення та стек
- •13.2.1 Синтаксис основних конструкцій
- •13.2.1.1 Використання try та сatch
- •13.2.1.2 Використання throw
- •13.2.2 Тип виключення та конструктор копії
- •13.2.3 Пошук відповідного типу виключення
- •13.2.4 Використання terminate() та некеровані виключення
- •13.2.5 Робота з специфікаціями виключень
- •13.2.6 Робота з непередбаченими виключеннями
- •13.2.7 Робота з конструкторами та виключеннями
- •13.2.8 Динамічні об’єкти
- •13.2.9 Передача значень з конструктора та деструктора
- •13.2.10 Робота з ієрархіями виключень
- •13.2.11 Робота з специфічними класами виключень
- •13.3 Структурне управління виключеннями
- •13.3.1 Використання кадрованого управління виключеннями
- •13.3.1.1 Синтаксис
- •13.3.1.2 Про функцію RaiseException()
- •13.3.1.3 Фільтруючий вираз
- •13.3.1.4 Перехоплення виключення процесора
- •13.3.2 Використання завершуючих обробників виключень
8.3 Віртуальні деструктори.
Деструктори, на вiдмiну вiд конструкторiв, можуть бути вiртуаль-ними. Синтаксично вони задаються як і звичайні віртуальні функціх за допомогою ключового слова virtual. Вiртуальнi деструктори використовуються у випадку, коли в деякому класi необхiдно знищити об'єкти похiдного класу, на якi посилаються вказiвники на базовий клас.
Розглянемо приклад:
class TBase{
private:
char*sp1;
public:
TBase(const char*s)
{sp1=strdup(s);}
virtual~TBase( )
{delete sp1;} };
class TDerived::public TBase{
private:
char*sp2;
public:
TDerived(const char*s1,const char*s2)/:TBase(s1)
{sp2=strdup(s2);}
virtual~TDerived( )
{delete sp2;}};
TBase*pbase;
pbase=new TDerived("string1","string2");
delete pbase; // s1-знищився,s2-залишився.
Якщо в даному прикладi деструктори не були б вiртуальними, то при виходi з областi видимостi об'кта класу Tderived, на який вказує вказiвник pbase, викличеться лище деструктор класу Tbase, тобто копiя рядка string2 залишиться в пам'ятi. Якщо ж деструктори оголошенi як вiртуальнi, то в данiй ситуацiї буде викликаний спочатку деструктор похiдного класу, а потiм i деструктор базового.
8.4 Посилання як засіб для реалізації поліморфізму
Для реалiзацiї полiморфiзму в С++, крiм вказiвників можна використовувати і посилання. Розглянемо наступний приклад:
#include "shape.h"
main
{circle c1;
Line l1,l2;
shape & pic0=c1
shape & pic1=l1;
shape & pic2=l2;
pic0.Draw ( );
pic1.Draw ( );
pic2.Draw ( );}
В цьому прикладі кожен виклик функції Draw() призводить до малювання відповідної фігури.
При передачi параметрiв вiртуальним функцiям може виникнути помилка. Виникає питання: коли здійснюється контроль помилок при передачі параметрів? Адже конкретна реалізація віртуальної функції зв’язується з об’єктом на етапі виконання програми. Що стосується С++, то контроль помилок при передачi параметрiв вiртуальним функцiям здiйснюється на етапi компiляцiї , а не виконання програми, тому що сигнатури вiртуальних функцiй повиннi жорстко спiвпадати.
8.5 Технічна реалізація механізму віртуальних функцій.
Екземпляр класу в С++ являє собою неперевну область в пам'ятi. Вказiвник на такий об'єкт мiстить початкову адресу цiєї областi. Коли викликається функцiя-член(об'єкту посилається повiдомлення), то цей виклик компiлюється у звичайний виклик функцiї з додатковим аргументом, який містить вказiвник на цей об'єкт. Тобто якщо в нас є такий виклик функції:
classname*object;
object->message(15);
то компiлятором він перетворюється в такий:
classname_mesage(object ,15);
Механiзм вiртуальних функцiй в С++ забезпечується за допомогою так званих таблиць віртуальних функцій(ТВФ).
1. ТВФ будується компiлятором автоматично для кожного класу, який має вiртуальнi функцiї i мiстить адреси вiртуальних функцiй, доступних в цьому класi;
2. Кожний екземпляр класу мiстить скритий вказiвник на його ТВФ;
3. Компiлятор автоматично вставляє в початок конструктора класу
фрагмент коду, який iнiцiалiзує вказiвник на ТВФ кожного класу;
4. Для будь-якої iєрархiї класiв адреса деякої вiртуальної функцiї має одне i теж змiщення в ТВФ кожного класу;
5. Пiд час виклику вiртуальних функцiй код, згенерований компiлятором, перш за все знаходить вказiвник вiртуальної таблицi, потiм вiдбувається звертання до ТВФ та знаходиться адреса вiртуальної функцiї i лише пiсля цього вiдбувається безпосереднiй виклик функцiї.
Приклад:
class Parent
{int value;
public:
virtual int method1(float r);
virtual void method2(void);
virtual float method3(char*s);
};
class child1:public Parent
{
public:
virtual void method2(void);
}
class child2:public child1
{
public:
virtual float method3(char*s);
}
Стосовно цього прикладу ТВФ можна уявити так:
//розглянемо клас Parent:
virtual_table1->
parent::method1
parent::method2
parent::method3
//для Child1:
virtual_table2->
parent::method1
child1::method2
parent::method3
//Беремо до уваги однаковість зміщення.
//для Child2:
virtual_table3=>
parent::method1
child1::method2
child2::method3
Тоді виклик виду:
child2 *c;
c->method3(string");
компiлятор перетворює в наступний:
(*(c=>virtual_table3[2]))(c,"string");