Розробка власного класу STRING

Курсовой проект - Компьютеры, программирование

Другие курсовые по предмету Компьютеры, программирование

одженню між операцією присвоювання й конструктором копіювання і еквівалентно розходженню між функціями _draw () і draw (). Відзначимо, що функція copy () не є віртуальною. Їй і не треба бути такою, оскільки віртуальна викликаюча її функція clone (). Очевидно, що прості операції копіювання можна також визначати як функції-підстановки.

 

1.15 Перевантаження операцій

 

Звичайно в програмах використовуються обєкти, що є конкретним поданням абстрактних понять. Наприклад, у С++ тип даних int разом з операціями +, - , *, / і т.д. реалізує (хоча й обмежено) математичне поняття цілого. Звичайно з поняттям звязується набір дій, які реалізуються в мові у вигляді основних операцій над обєктами, що задають у стислому, зручному й звичному виді. На жаль, у мовах програмування безпосередньо представляється тільки мале число понять. Так, поняття комплексних чисел, алгебри матриць, логічних сигналів і рядків у С++ не мають безпосереднього вираження. Можливість задати подання складних обєктів разом з набором операцій, котрі виконуються над такими обєктами, реалізують у С++ класи. Дозволяючи програмістові визначати операції над обєктами класів, ми одержуємо більше зручну й традиційну систему позначень для роботи із цими обєктами в порівнянні з тієї, у якій всі операції задаються як звичайні функції. Приведемо приклад:

 

class complex {

double re, im;

public:

complex (double r, double i) { re=r; im=i; }

friend complex operator+ (complex, complex);

friend complex operator* (complex, complex);

};

 

Тут наведена проста реалізація поняття комплексного числа, коли воно представлено парою чисел із плаваючою крапкою подвійної точності, з якими можна оперувати тільки за допомогою операцій + і *. Інтерпретацію цих операцій задає програміст у визначеннях функцій з іменами operator+ і operator*. Так, якщо b і c мають тип complex, те b+c означає (по визначенню) operator+ (b,c). Тепер можна наблизитися до звичного запису комплексних виражень:

 

void f ()

{

complex a = complex (1,3.1);

complex b = complex (1.2,2);

complex c = b;

a = b+c;

b = b+c*a;

c = a*b+complex (1,2);

}

Зберігаються звичайні пріоритети операцій, тому другий вираз виконується як b=b+ (c*a), а не як b= (b+c) *a.

 

1.15.1 Операторні функції

Можна описати функції, що визначають інтерпретацію наступних операцій:

 

+ - * /% ^ & | ~!

= += - = *= /=%= ^= &=

|= = &&

|| ++ - і - >*, - > [] () new delete

 

Останні пять операцій означають: непряме звертання, індексацію, виклик функції, розміщення у вільній памяті й звільнення. Не можна змінити пріоритети цих операцій, так само як і синтаксичні правила для виразів. Так, не можна визначити унарну операцію%, також як і бінарну операцію!. Не можна ввести нові лексеми для позначення операцій, але якщо набір операцій вас не влаштовує, можна скористатися звичним позначенням виклику функції. Тому використайте pow (), а не **. Ці обмеження можна ввжати драконівськими, але більш вільні правила легко приводять до неоднозначності. Припустимо, ми визначимо операцію ** як піднесення до степеня, що на перший погляд здається очевидним і простим завданням. Але якщо як варто подумати, то виникають питання: чи належні операції ** виконуватися ліворуч праворуч або праворуч ліворуч? Як інтерпретувати вираження a**p як a* (*p) або як (a) ** (p)?

Імям операторної функції є службове слово operator, за яким іде сама операція, наприклад, operator<<. Операторна функція описується й викликається як звичайна функція. Використання символу операції є просто короткою формою запису виклику операторної функції:

void f (complex a, complex b)

{

complex c = a + b; // коротка форма

complex d = operator+ (a,b); // явний виклик

}

 

З урахуванням наведеного опису типу complex ініціалізатори в цьому прикладі є еквівалентними.

 

1.15.2 Бінарні й унарні операції

Бінарну операцію можна визначити як функція-член з одним параметром, або як глобальну функцію із двома параметрами. Виходить, для будь-якої бінарної операції @ вираження aa @ bb інтерпретується або як aa. operator (bb), або як operator@ (aa,bb). Якщо визначені обидві функції, то вибір інтерпретації відбувається за правилами зіставлення параметрів. Префіксна або постфіксна унарна операція може визначатися як функція-член без параметрів, або як глобальна функція з одним параметром. Для будь-якої префиксної унарної операції @ вираження @aa інтерпретується або як aa. operator@ (), або як operator@ (aa). Якщо визначені обидві функції, то вибір інтерпретації відбувається за правилами зіставлення параметрів. Для будь-якої постфіксної унарної операції @ вираз @aa інтерпретується або як aa. operator@ (int), або як operator@ (aa, int). Якщо визначені обидві функції, то вибір інтерпретації відбувається за правилами зіставлення параметрів. Операцію можна визначити тільки відповідно до синтаксичних правил, наявними для неї в граматиці С++. Зокрема, не можна визначити% як унарну операцію, а + як тернарну. Проілюструємо сказане прикладами:

 

class X {

// члени (неявно використається покажчик this):

X* operator& (); // префіксна унарная операція &

// (узяття адреси)

X operator& (X); // бінарна операція &

X operator++ (int); // постфіксний інкремент

X operator& (X,X); // помилка: & не може бути тернарною

X operator/ (); // помилка: / не може бути унарною

};

// глобальні функції (звичайно друзі)

X operator- (X); // префіксний унарный мінус

X operator- (X,X); // бінарний мінус

X operator-і (X&, int); // постфіксни?/p>