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

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

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

° визначити функцію, що множить матрицю на вектор. Для простоти припустимо, що вектор має чотири елементи з індексами від 0 до 3, а в матриці чотири вектори теж з індексами від 0 до 3. Доступ до елементів вектора забезпечується функцією elem (), і аналогічна функція є для матриці. Можна визначити глобальну функцію multiply (помножити) у такий спосіб:

 

vector multiply (const matrix& m, const vector& v);

{

vector r;

for (int i = 0; i<3; i++) { // r [i] = m [i] * v;

r. elem (i) = 0;

for (int j = 0; j<3; j++)

r. elem (i) +=m. elem (i,j) * v. elem (j);

}

return r;

}

Це цілком природнє рішення, але воно може виявитися дуже неефективним. При кожному виклику multiply () функція elem () буде викликатися 4* (1+4*3) раз. Якщо в elem () проводиться контроль границь масиву, то на такий контроль буде витрачено значно більше часу, ніж на виконання самої функції, і в результаті вона виявиться непридатної для користувачів. З іншого боку, якщо elem () є якийсь спеціальний варіант доступу без контролю, то тим самим ми засмічуємо інтерфейс із вектором і матрицею особливою функцією доступу, що потрібна тільки для обходу контролю.

Якщо можна було б зробити multiply членом обох класів vector і matrix, ми могли б обійтися без контролю індексу при звертанні до елемента матриці, але в той же час не вводити спеціальної функції elem (). Однак, функція не може бути членом двох класів. Треба мати в мові можливість надавати функції, що не є членом, право доступу до приватних членів класу. Функція - не член класу, але має доступ до його закритої частини, називається другом цього класу. Функція може стати другом класу, якщо в його описі вона описана як friend (друг). Наприклад:

 

class matrix;

class vector {

float v [4];

// ...

friend vector multiply (const matrix&, const vector&);

};

class matrix {

vector v [4];

// ...

friend vector multiply (const matrix&, const vector&);

};

Функція-друг не має ніяких особливостей, за винятком права доступу до закритої частини класу. Зокрема, у такій функції не можна використати вказівник this, якщо тільки вона дійсно не є членом класу. Опис friend є дійсним описом. Воно вводить імя функції в область видимості класу, у якому вона була описана, і при цьому відбуваються звичайні перевірки на наявність інших описів такого ж імені в цій області видимості. Опис friend може перебуває як у загальній, так і в приватній частинах класу, це не має значення.

Тепер можна написати функцію multiply, використовуючи елементи вектора й матриці безпосередньо:

 

vector multiply (const matrix& m, const vector& v)

{

vector r;

for (int i = 0; i<3; i++) { // r [i] = m [i] * v;

r. v [i] = 0;

for (int j = 0; j<3; j++)

r. v [i] +=m. v [i] [j] * v. v [j];

}

return r;

}

 

Відзначимо, що подібно функції-члену дружня функція явно описується в описі класу, з яким дружить. Тому вона є невідємною частиною інтерфейсу класу нарівні з функцією-членом.

Функція-член одного класу може бути другом іншого класу:

 

class x {

// ...

void f ();

};

class y {

// ...

friend void x:: f ();

};

 

Цілком можливо, що всі функції одного класу є друзями іншого класу. Для цього є коротка форма запису:

 

class x {

friend class y;

// ...

};

 

У результаті такого опису всі функції-члени y стають друзями класу x.

 

1.14 Ядро ООП: Успадкування та поліморфізм

 

Ця глава присвячена поняттю похідного класу. Похідні класи - це простий, гнучкий і ефективний засіб визначення класу. Нові можливості додаються до вже існуючого класу, не вимагаючи його перепрограмування або перетрансляції. За допомогою похідних класів можна організувати загальний інтерфейс із декількома різними класами так, що в інших частинах програми можна буде одноманітно працювати з обєктами цих класів. Вводиться поняття віртуальної функції, що дозволяє використати обєкти належним чином навіть у тих випадках, коли їхній тип на стадії трансляції невідомий. Основне призначення похідних класів - спростити програмістові завдання вираження спільності класів.

 

1.4.1 Похідні класи

Обговоримо, як написати програму обліку службовців деякої фірми. У ній може використатися, наприклад, така структура даних:

 

struct employee { // службовець

char* name; // імя

short age; // вік

short department; // відділ

int salary; // оклад

employee* next;

// ...

};

 

Поле next потрібно для звязування в список записів про службовців одного відділу (employee). Тепер спробуємо визначити структуру даних для керуючого (manager):

 

struct manager {

employee emp; // запис employee для керуючого

employee* group; // підлеглий колектив

short level;

// ...

};

 

Керуючий також є службовцем, тому запис employee зберігається в члені emp обєкта manager. Для людини ця спільність очевидна, але для транслятора член emp нічим не відрізняється від інших членів класу. Вказівник на структуру manager (manager*) не є вказівником на employee (employee*), тому не можна вільно використати один замість іншого. Зокрема, без спеціальних дій не можна обєкт manager включити до списку обєктів типу employee. Доведеться або використати явне приведення типу manager*, або в список записів employee включити адресу члена emp. Обоє рішень некрасиві й можуть бути досить заплутаними. Правильне рішення полягає в тому, щоб тип manager був типом employee з деякою додатковою інформацією:

 

struct manager: employee {

employee* group;

short level;

// ...

};

 

Клас manager є похідн