
- •1 Парадигми та мови програмування
- •1.1 Процедурне програмування
- •1.2 Об'єктне (модульне) програмування
- •1.3 Об'єктно-орієнтовне програмування
- •2 Програмне середовище
- •3 Базові поняття програмування
- •4 Процедурно-орієнтоване програмування
- •4.1 Функції
- •4.2 Вбудовані (inline) функції
- •4.3 Передача параметрів
- •4.4 Обчислення значення функцій
- •4.4. Обчислення значення функції — вихід із функції; особливості повернення та використання іменованого значення, іменованої константи
- •4.5 Рекурсія
- •4.6 Довизначення (overloading) функцій
- •4.6. Довизначення (overloading) функцій
- •4.7 Узагальнені функції (function template)
- •4.8 Непряме використання функцій: указники на функції, їх тип, ініціалізація і присвоєння
- •4.9 Видимість
- •4.10 Тривалість життя об’єктів
- •5 Об'єктне програмування
- •5.1 Класи і об'єкти, члени класів
- •5.2 Інтерфейс класу, реалізація класу; визначення і оголошення класу
- •5.3 Створення і ініціалізація об'єктів, довизначення конструкторів, замовчуваний конструктор, копіювання, поверхневе і глибоке копіювання, ініціалізація і присвоєння, копіювальний конструктор
- •5.4 Cтатичні члени класів і статичні класні функції
- •5.5 Константні об'єкти, константні функції, змінювані члени константних об'єктів (mutable)
- •5.6 Поточний об'єкт this, указники на члени класу і класні функції, порівняння з указниками на (позакласні) функції, указники на статичні члени класу
- •5.7 5.8. Довизначення (overloading) операцій
- •5.7 5.8. Довизначення (overloading) операцій
- •5.7 5.8. Довизначення (overloading) операцій
- •5.7 5.8. Довизначення (overloading) операцій
- •5.7 5.8. Довизначення (overloading) операцій
- •5.7 5.8. Довизначення (overloading) операцій
- •5.8 Клас string: конструктори і присвоєння рядків, операції, відкладене копіювання
- •5.9 Параметризовані класи (class template): визначення шаблону, конкретизація
- •6 Об'єктно-орієнтовне програмування
- •6.1 Ієрархія об’єктів і ієрархія класів
- •6.2 Відкрите, закрите і захищене успадкування, успадкування типу і успадкування реалізації; абстрактні класи
- •6.3 Створення похідних об'єктів
- •6.4 Статичне і динамічне зв’язування
- •6.5 Успадкування із спільного базового класу. Кратне (multiple) успадкування. Віртуальне успадкування, порядок виклику конструкторів
- •7 Екзаменаційні завдання
- •7 Екзаменаційні завдання
5.7 5.8. Довизначення (overloading) операцій
Складніші варіанти присвоєння розглянемо у наступному розділі.
Унарні арифметичні операції інкременту і декременту довизначаються в дещо
умовний спосіб, що ілюструється наступним прикладом.
Розглянемо клас
class Time
{
private:
short hours;
short minutes;
short seconds;
//Функція службова, а тому закрита
void NormalizeTime();
public:
Time();
Time( short h, short m, short s );
void Display();
Time operator+(const Time &aTime );
Time& operator*=( short num );
Time operator++ ();
Time operator++ ( int );
};
та його реалізацію
#include <iostream>
using namespace std;
#include "Time.h"
Time::Time()
{
seconds = 0;
minutes = 0;
hours = 0;
}
Time::Time( short h, short m, short s )
{
seconds = s;
minutes = m;
hours = h;
NormalizeTime();
}
void Time::NormalizeTime()
{
hours += ((minutes + (seconds/60)) / 60);
minutes = (minutes + (seconds/60)) % 60;
seconds %= 60;
}
void Time::Display()
{
cout << "(" << hours <<":" << minutes
<< ":" << seconds << ")\n";
}
Time Time::operator+(const Time &aTime )
{
short h;
short m;
short s;
h = hours + aTime.hours;
m = minutes + aTime.minutes;
s = seconds + aTime.seconds;
Time tempTime( h, m, s );
return tempTime;
}
Time& Time::operator*=( short num )
{
hours *= num;
minutes *= num;
seconds *= num;
NormalizeTime();
return *this;
}
Time Time::operator++ ()
{
//Унарна операція, тому параметру немає
this->hours += 1;
return *this;
}
Time Time::operator++ ( int )
{
//Теж унарна операція
//Параметр не використовується і не визначається
//Він служить лише для того, щоб формально відрізняти
//реалізацію постфіксної операції від префіксної
Time aTime = *this;
this->hours += 1;
return aTime;
}
разом з тестувальною програмою
int main()
{
Time firstTime( 1, 10, 50 );
Time secondTime( 2, 24, 20 );
Time sumTime;
firstTime.Display();
cout<<'+'<<endl;
secondTime.Display();
cout << "---------\n";
sumTime = firstTime + secondTime;
sumTime.Display();
cout << "* 2\n";
cout << "---------\n";
sumTime *= 2;
sumTime.Display();
firstTime=sumTime++;
firstTime.Display();
sumTime.Display();
firstTime=++sumTime;
firstTime.Display();
return 0;
}
Продовжимо вивчення операцій, що підлягають довизначенню. Зараз мова піде
про операції, які реалізуються виключно членами класу. Реалізація утилітами
для них неможлива.
Розміщення та знищення об'єкту . Унарні операції
new та delete теж реалізуються особливо. Спочатку розглянемо приклад
class Blob
{
public:
void* operator new( size_t blobSize );
void operator delete(void *blobPtr,size_t blobSize);
};
Параметр для унарного оператора new х готується спеціально. Його обчислює
компілятор, виходячи з типу х . Оператор new повертає безтиповий указник на
виділену пам'ять. Значення параметру blobSize передвизначеного типу size_t
автоматично обчислюється компілятором. Цей параметр визначає об'єм пам'яті,
що виділятиметься. Якщо планується передавати також інші параметри, вони розташовуються
за ним.
void *Blob::operator new( size_t blobSize )
{
cout << "new: " << blobSize << " byte(s).\n";
return new char[ blobSize ];
}
Оператор delete ніколи не повертає значення. Він вимагає принаймні одного
параметру, а саме: безтипового указника на блок, що витиратиметься. Може бути
і другий параметр, який система програмування формує, виходячи з класу, в якому
довизначається оператор
delete
. Тоді маємо сигнатуру operator
delete(*void,
size_t)
. Другий параметр не обов'язковий, він буде потрібен, коли з'явиться
ієрархія класів з віртуальними деструктори (див. наступний розділ).
void Blob::operator delete(void *blobPtr,size_t blobSize)
{
cout << "delete: " << blobSize << " byte(s).\n";
delete [] blobPtr;
}
Ось приклади виклику:
Blob *blobPtr;
blobPtr = new Blob;
delete blobPtr;
Буде виділено 1 байт — стільки місця займають об'єкти без атрибутів. Поекспериментуйте
з розмірами об'єкту, додаючи в клас Blob атрибути.
Операція виклику функції . Спочатку
займемося створенням так званих функції-подібних об'єктів . Один з
них ми вже знаємо — це указники на функції, наприклад,
double (*f)(double)
, до яких також можна застосовувати операцію виклику f(a) . В такий спосіб
можна довизначити операцію виклику функції власне для довільного функції-подібного
об'єкта, наприклад, товару:
#include <iostream.h>
//Об’єкти класу Item призначені для продажу.
//В їх ціну входить ставка ПДВ.
class Item
{
private:
double price;
public:
Item( double itemPrice );
double operator()( double vat = 0 );
};
Item::Item( double itemPrice )
{
price = itemPrice;
}
double Item::operator()( double vat )
{
return( ((vat * .01) + 1) * price );
}