Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Конспект лекцій по С.doc
Скачиваний:
1
Добавлен:
01.04.2025
Размер:
7.72 Mб
Скачать

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 );

}