Студопедия

КАТЕГОРИИ:


Архитектура-(3434)Астрономия-(809)Биология-(7483)Биотехнологии-(1457)Военное дело-(14632)Высокие технологии-(1363)География-(913)Геология-(1438)Государство-(451)Демография-(1065)Дом-(47672)Журналистика и СМИ-(912)Изобретательство-(14524)Иностранные языки-(4268)Информатика-(17799)Искусство-(1338)История-(13644)Компьютеры-(11121)Косметика-(55)Кулинария-(373)Культура-(8427)Лингвистика-(374)Литература-(1642)Маркетинг-(23702)Математика-(16968)Машиностроение-(1700)Медицина-(12668)Менеджмент-(24684)Механика-(15423)Науковедение-(506)Образование-(11852)Охрана труда-(3308)Педагогика-(5571)Полиграфия-(1312)Политика-(7869)Право-(5454)Приборостроение-(1369)Программирование-(2801)Производство-(97182)Промышленность-(8706)Психология-(18388)Религия-(3217)Связь-(10668)Сельское хозяйство-(299)Социология-(6455)Спорт-(42831)Строительство-(4793)Торговля-(5050)Транспорт-(2929)Туризм-(1568)Физика-(3942)Философия-(17015)Финансы-(26596)Химия-(22929)Экология-(12095)Экономика-(9961)Электроника-(8441)Электротехника-(4623)Энергетика-(12629)Юриспруденция-(1492)Ядерная техника-(1748)

Також можливе довизначення багатьох інших операцій

Довизначення (overloading) операцій

Довизначення (overloading) операцій: арифметичні операції (бінарні, унарні, суміщені з присвоєнням), оператори управління пам'яттю, оператор виклику функції, оператор доступу до елементу масиву, оператор доступу за указником, оператор присвоєння,

 

Визначаючи за допомогою класу новий тип, ми вбудовуємо його в наявне середовище

із своєю системою позначень і понять. Вбудовування це стане найбільш природним

і адекватним, якщо ми збережемо значення вже наявних позначень, довизначивши

та розширивши їх на нові об'єкти. Ось типова схема визначення класу

 

Class T

{

 

//Мінімальний набір:

//конструктор

T(t,…,s);

//конструктор копіювання

T(const T&);

//присвоєння глибоким копіюванням

T& operator=(const T&);

//деструктор

~T();

 

 

//Можливі операції:

//бінарні арифметичні операції

T operator?(const T&) const;

//вони ж, сполучені з присвоєнням

T& operator?=(const T&);

//приведення типу T до типу S

operator S();

 

 

//Особливості реалізації:

//інфіксного декременту (звичайний спосіб)

T operator++();

//постфіксного інкременту (фіктивний параметр)

T operator++(int);

 

 

//Можливі непорозуміння:

//обчислення адреси

T* operator&() const;

//кон’юнкція

T operator&(const T&);

 

 

}

 

З мінімальним набором засобів у визначеному класі ми вже певною мірою знайомилися.

Присвоєння потребує довизначення лише при необхідності глибокого копіювання,

оскільки поверхневе копіювання передвизначене для кожного класу. Присвоєння,

суміщене з операціями, потребує спеціального довизначення. Розглянемо арифметичні

операції. Для цього визначимо дуже спрощений клас комплексних чисел

 

class complex

{

double _re, _im;

public:

complex (double r=0,double i=0):_re(r),_im(i){};

complex (const complex& c):_re(c._re),_im(c._im){};

complex operator+ (const complex&) const;

complex& operator+= (const complex&);

double re() const {return _re;}

double im() const {return _im;}

};

 

Проаналізуємо його. Конструктор має замовчування: complex z; надасть об'єкту

z значення 0; complex z1(1); створить об'єкт з нульовою уявною частиною. Деструктор

не потрібен, довизначення присвоєння теж.

 

Обмежимося поки що однією арифметичною операцією додавання. Цілком очевидно,

чого варто сподіватися після виконання наступного фрагменту програми

 

complex u(1,1), v(2, 2),w;

 

w=u+v;

 

Трохи менш зрозумілим буде інший фрагмент

 

complex u(1,1), w;

 

w=u+1;

 

очевидно, що очікується збільшення дійсної частини на 1. Залишилося лише зрозуміти,

як це відбувається. Для цього помітимо, що конструктор комплексного числа задає,

крім всього іншого, перетворення дійсного числа в комплексне, наприклад, complex(1)

перетворює дійсну одиницю на комплексне число, дійсна частина якого одиниця.

Оскільки операції додавання з сигнатурою (complex, double) немає, відбувається

підвищення типу дійсного до комплексного. Насправді присвоєння w=u+1; виконається

як w=u+complex(1). Тобто щось на зразок

 

complex * tmp = new complex(1);

 

w = u+*tmp;

 

Якби ж ми доповнили б інтерфейс функцією

 

complex operator+ (double) const;

 

була б викликана вона і додатковий об'єкт не створювався б.

 

Те ж саме стосується оператора додавання з присвоєнням

 

complex u(1,1);

 

u+=1;

 

Реалізації операцій досить очевидні

 

complex& complex::operator+= (double a)

{

_re += a;

return *this;

}

complex complex:: operator+ (double a)const

{

complex res = *this;

return res+=a;

}

 

Залишилася лише одна проблема, викликана бажанням зберегти комутативність

операції додавання

 

complex u(1,1), w;

 

w=1+u;

 

присвоєння з явним конструктором проходить без проблем

 

w = complex(1)+u;

 

Неявне перетворення типів, можливе для другого аргументу, для першого виявилося

неможливим. Чому? Відповідь зрозуміла. Як ми пам'ятаємо, класна функція, додатково

до своїх параметрів містить ще указник на поточний об'єкт this, з яким цей

метод безпосередньо працює. В нашому випадку цього об'єкту немає, його роль

мусив би відігравати тимчасовий об'єкт, а це було б не зовсім коректно, оскільки

об'єкт, що активізує метод, повинен жити довше, ніж період активності методу

(тимчасові об'єкти ліквідуються при виході із функції)

 

complex * tmp = new complex(1);

w = tmp + u;

 

Прирівняти в правах перший параметр з другим можна, винісши додавання за межі

класу

 

complex operator+(const complex& a, const complex& b)

{

complex res=a;

return res+=b;

}

 

Тепер при необхідності виконати перетворення першого параметру викликатиметься

не класна функція додавання, а утиліта класу.

 

Ще дві корисні утиліти:

 

complex operator==(const complex& a, const complex& b)

{

return (a.re()==b.re()) && (a.im()==b.im());

}

ostream& operator<<(ostream &os, const complex& a)

{

os<<"re="<<a.re()<<" im="<<a.im()<<endl;

return os;

}

 

 

Детальніше про ввід-вивід у наступному підрозділі. Перейдемо тепер до множення

комплексних чисел. Як відомо, множення простіше виконується над комплексними

числами у тригонометричній формі. Визначимо новий клас

 

class Tcomplex

{

friend class complex;

double _rho, _phi;

public:

Tcomplex (double r=0,double a=0): _rho(r),_phi(a){};

operator complex ();

Tcomplex operator*(const Tcomplex&) const;

Tcomplex operator*=(const Tcomplex&);

double rho() const { return _rho;}

double phi() const { return _phi; }

};

 

Все, що тут написано, є очевидним аналогом класу комплексних чисел у алгебраїчній

формі, крім оператора complex() перетворення тригонометрич­ного комплексного

числа в алгебраїчне. Ось його реалізація

 

Tcomplex::operator complex()

{

complex res(_rho*cos(_phi),_rho*sin(_phi));

return res;

}

 

Аналогічним перетворенням можна поповнити клас комплексних чисел

 

Tcomplex::operator complex()

{

complex res(_rho*cos(_phi),_rho*sin(_phi));

return res;

}

 

додавши його оголошення також до інтерфейсу. Тепер можливі змішані вирази

з комплексних чисел. Для додавання тригонометричні будуть перетворюватися в

алгебраїчну форму, для множення — навпаки.

 

class complex

{

double _re, _im;

public:

complex (double r=0,double i=0):_re(r),_im(i){};

complex (const complex& c):_re(c._re),_im(c._im){};

complex operator+ (const complex&) const;

complex& operator+= (const complex&);

double re() const {return _re;}

double im() const {return _im;}

operator Tcomplex();

bool operator!= (const complex& a)

{return!(*this==a);}

complex operator- (const complex&) const;

complex& operator-= (const complex&);

};

 

Пам'ятаємо, що перетворення типів чи довизначення функцій можуть бути альтернативою

одне іншому. Яку з них обирати, залежить від додаткових вимог до задачі.

 

Тепер розглянемо нечисловий приклад.

 

class MenuItem

{

private:

float price;

string name;

public:

MenuItem(float, string);

MenuItem(float, char[]);

MenuItem(const MenuItem&);

float getPrice();

};

 

Припустимо, що було зроблено замовлення:

 

MenuItem chicken(8.99, ”Київські котлети”);

MenuItem wine(2.99, ”Каберне”);

MenuItem pie(5.98,”Київський торт”);

float total;

 

<== предыдущая лекция | следующая лекция ==>
Поточний об'єкт this, указники на члени класу і класні функції, порівняння з указниками на (позакласні) функції, указники на статичні члени класу | Довизначення (overloading) операцій
Поделиться с друзьями:


Дата добавления: 2014-01-06; Просмотров: 240; Нарушение авторских прав?; Мы поможем в написании вашей работы!


Нам важно ваше мнение! Был ли полезен опубликованный материал? Да | Нет



studopedia.su - Студопедия (2013 - 2024) год. Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав! Последнее добавление




Генерация страницы за: 0.011 сек.