
- •Концепції ооп
- •3 Класи. Формат оголошення класів. Специфікатори прав доступу. . Створення об’єктів. Доступ до елементів класу
- •Cтатичні члени класів і статичні класні функції
- •12. Поняття перевантаження функції . Правила перевантаження функції. Приклади перевантаження функції – методів класу ( конструкторів). Аргументи за замовчуванням .
- •Аргументи за замовчуванням
- •15. Статичні члени класу.
- •Cтатичні члени класів і статичні класні функції
- •26. Передача параметрів конструкторам базового класу. Навести приклади
- •31. Чисто віртуальні функції. Абстрактні класи. Навести приклади.
15. Статичні члени класу.
Cтатичні члени класів і статичні класні функції
Доповнимо клас Employee визначенням вільного ідентифікаційного коду службовця. Самий простий спосіб — оголосити його статичною змінною:
static unsigned int currentId;
інкапсулювавши її клас, для чого її оголошення розміщується в його інтерфейсі. Як ми пам'ятаємо, атрибути ініціалізуються особливо. Звичайні атрибути — при створенні об'єкта. Статичний атрибут спільний для всіх об'єктів класу, а тому ідентифікується без посилання на об'єкт і створюється компонувальником за його визначенням, яке розміщується у файлі реалізації
unsigned int Employee :: currentId = 0;
Відповідних змін може зазнати конструктор, в якому тепер стане на параметр менше. Залежно від обставин ним може виявитися додатково довизначений конструктор
16. Основи перевантаження операторів. Перевантаження бінарного оператора . (+)..Правила перевантаження операторів. Навести приклади.
Оператори С++ представляють собою альтернативний запис виклику функцій асоційованих з математичними та логічними функціями. Вони вбудовані в мову і використовуються для певних дій (операцій) з вбудованими типами.
Подібність між операторами та викликами функцій дозволяє створення користувацьких (перевантажених) операторів, які будуть коректно працювати з різними типами об’єктів, які є екземплярами користувацьких класів. Це дає можливість створювати самодостатні програмні конструкції із своїм набором дій, який уніфікований за викликами із стандартним набором.
Перевантаження операторів задумане з метою спрощення запису та уніфікації виразів. Більше того, перевантажені оператори можуть наслідуватись. Власне поширення концепції перевантаження операторів еквівалентне звертанню до функцій і є новим в С++.
Відомо оператори, як функції, можуть співставлятись з об’єктами двома методами: як функції-члени і як друзі (чи звичайні сторонні функції). Так, наприклад, застосування унарного операції ~ (інверсія бітів) до об’єкта ~W, може бути записано у двох формах виклику функції operator~():
W.operator~(); // як функція-член
operator~(W); // як дружня (чи просто стороння) функція
Бінарні оператори можна записати подібно. Наприклад, операція додавання + по відношенню до двох об’єктів X та Y (тобто X+Y) еквівалентна викликам:
X.operator+(Y); // як функція-член
operator+(X,Y); // як дружня (чи просто стороння) функція
Виклик X.operator+(Y) передбачає, що функція operator+()є методом об’єкта X тобто першого операнда. Це означає, що в цьому випадку оператори не комутативні, оскільки операнд X може бути екземпляром зовсім іншого типу, а оператор Y.operator+(X) в даному випадку не розглядається.
З прикладів видно, що оператори можуть використовують дві різні функції, які, в загальному випадку, можуть зреалізовувати зовсім різні дії. У випадку, коли компілятору доступні обидві версії, починає працювати механізм визначення сумісності типів. Якщо правилу сумісності відповідають обидві функції, то генерується помилка.
Зауважим, що випадку n-арного оператора як дружньої випадку, функція оператор приймає n аргументів. У випадку методі класу - (n-1) аргумент. Тобто, арність оператора однозначно визначає кільіксть параметрів при перевантаженні оператора. Наприклад унарний оператор у випадку методу класу однозначно не приймає жодних аргументів.
Необхідно пам’ятати про обмеження, які супроводжують використання перевантажених операторів
1. Перевантажені функції не можуть змінити пріорітет операторів.
2. Кількість операндів є фіксованим.
3. Значення операндів не можна задавати по замовчуванні.
17. Перевантаження оператора привласнення (=). Правила перевантаження операторів. Навести приклади.
Оператор присвоєння (operator=()) - є бінарми оператором, але може бути перевантажений лише як метод класу, а не як дружня функція. Відповідно до цього перевантажений в класі operator= є унарною функцією.
Якщо явно оператор присвоєння не визначений, то автоматично згенерується оператор по замовчуванню, який побайтно буде здійснювати копіювання. В окремих випадках оператор присвоєння може бути замінений конструкторм копії.
Приклад 2.5.8
#include <iostream>
using namespaсe std;
class A
{
public:
int i;
A()
{
i = 0;
}
A(int i)
{
this->i = i;
}
A& operator= (A& a)
{
i=a.i;
return *this;
}
show()
{
cout<<" i="<<i<< endl;
}
};
void main()
{
A a, a1(10);
a = a1;
a.show();
}
Перевантажений оператор присвоєння повинен завжди повертати посилання на неконстантний об’єкт. Відповідно до цього тіло оператора повинно закінчуватиcь таким кодом: return *this. Це означає, що operator=() повернув управління об’єкту, який його викликав.
18. Перевантаження оператора інкременту ++ ( префіксна та постфіксна форми). Правила перевантаження операторів. Навести приклади.
Префіксні оператори (operator++(), operator--()) - є унарною операцією. Може перевантажуватись лише як метод класу. Відповідно до цього перевантажені в класі префіксні оператори є функціями без параметрів. Деякі компілятори можуть дозволяти оголошення їх окремих перевантажених версій (де не використовується вказівник this) статичними.
Оголошення префіксного оператора без параметра реалізовує його як чисто префіксний оператор (тобто у формі ++x), а з параметром типу int - постпрефіксним (тобто у формі x++). Даний параметр не використовується в тілі оператора, а є лише прапорцем схеми обчислень префіксного оператора.
Приклад 2.5.13
#include <iostream>
using namespaсe std;
class A
{
public:
int i;
A()
{
i = 0;
}
A(int i)
{
this->i = i;
}
int operator++ (int ) // постпрефіксна форма
{
int i = this->i;
this->i++;
return i;
}
int operator++ () // префіксна форма
{
i++;
return i;
}
show()
{
cout<<" A::i="<<i<< endl;
}
};
void main()
{
A a(5);
int j =a++; // постпрефіксна форма
cout<<" j="<<j;
a.show();
a.i=5;
j =++a; // префіксна форма
cout<<" j="<<j;
a.show();
}
19. Перевантаження оператора декременту -- ( префіксна та постфіксна форми). Правила перевантаження операторів. Навести приклади.
В 18 питанні відповідь
20. Перевантаження операторів відношення та логічних операторів. Правила перевантаження операторів. Навести приклади.
Всі операції відношення: = (дорівнює), <>(не дорівнює), < (менше), >(більше), <=(менше або дорівнює), >=(більше або дорівнює) дають результат типу boolean. Нижче наведені логічні операції в порядку зменшення їх пріоритету, причому операції, записані в одному пункті мають однаковий пріоритет: 1) Not; 2) And; 3) Or, Xor; 4) =, <>, <, >, <=, >=.
Якщо у виразі не використовують круглі дужки, то логічні операції виконуються в порядку зменшення їх пріоритетів. Операції однакового рангу виконуються зліва направо. Для зміни порядку виконання операцій в логічних виразах використовують круглі дужки.
Наприклад, обчислення виразу
(A=B) and (C<=D)
буде виконуватись в такій послідовності: спочатку визначається значення підвиразу A=B, потім підвиразу C<=D і тільки після цього виконується логічна операція And.
21. Перевантаження оператора виведення із потоку (<<). Правила перевантаження операторів.
Операція «помістити в потік» << – виведення у потік елементів даних вбудованих типів, виведення рядків і виведення значень вказівників. Для виведення виразів необхідно їх розміщувати у круглих дужках (), щоб не було проблем під час виконання операцій обчислення значень у виразах, і операції <<
22. Перевантаження оператора введення в поток (>>). Правила перевантаження операторів. Навести приклади
Операція введення потоку («узяти з потоку» >>) ігнорує у вхідному потоці символи-роздільники (пробіли, знаки табуляції, знак нового рядка). Вона повертає нульове значення (false), коли натрапляє в потоці на ознаку кінця файлу, або повертає посилання на об’єкт, з якого вона викликалася у противному випадку. Вона також установлює біт faіlbіt у разі введення даних неправильного типу і встановлює біт badbіt у випадку неуспішного завершення операції. Кожен потік – це біти стану, застосовувані для керування станом.
23. Поняття наслідування. Просте наслідування. Види наслідування. Управління доступом до базового класу
Наслідування – це процес створення нового класу шляхом додавання нових членів до вже існуючого класу.
Просте наслідування – це створення класу на основі одного.
Множинне наслідування – це створення класу на основі двох чи більше класів.
Статус доступу членів базового класу в похідному класі визначається специфікатором доступу, що використовується для наслідування базового класу.
24. Захищені члени класу. Використання захищених членів.
Захищений рівень доступу пояснити дещо складніше. До захищених членів класу, як і до закритих, користувач звертатися не може. Проте ці члени можуть бути доступні для класів, які є похідними даного класу.
25. Застосування наслідування. Конструктори , деструктори і наслідування. Порядок виклику конструкторів та деструкторів.
Застосування механізму успадкування дозволяє покращити повторне використання коду шляхом використання вже визначених властивостей та 09051004010031000102000018методів (поведінки) базових класів.
Конструктор – це спец. функція, яка призначена для ініціалізації об’єкту і яка викликається автоматично, неявно, після створення об’єкту.
Деструктор – це спец. програма, яка викликається автоматично, неявно в момент знищення об’єкту.
Успадкува́ння (наслідування) — механізм утворення нових 090001010031000102000018класів на основі використання вже існуючих. При цьому властивості і функціональність батьківського класу переходять до класу нащадка(дочірнього).
Порядок виклику деструкторів є таким як у конструкторів, а виконання - зворотнім. Найпершим почне виконуватись деструктор похідного класу, а далі - деструктори вітки породженої останнім в оголошенні батьківським класом. У порядку зворотньому до декларації батьківських класів відпрацють деструктори класів усіх віток від них породжених. Лише по закінченню роботи і закритття батьківських деструкторів закриється деструктор похідного класу.