Термінова допомога студентам
Дипломи, курсові, реферати, контрольні...

Визначається Перетворення Типу

РефератДопомога в написанніДізнатися вартістьмоєї роботи

Самый загальний підхід враховував б весь інформацію про типах і розглядав б, усе можливі перетворення. Наприклад, якщо використовувати попереднє опис, можна було б обробити aa=f (1), оскільки тип aa визначає одиничність тлумачення. Якщо aa є x, то єдине, дає внаслідок x, потрібного присвоюванням, — це f (x (1)), і якщо aa — це y, то натомість використовуватиметься f (y (1)). Найбільш загальний… Читати ще >

Визначається Перетворення Типу (реферат, курсова, диплом, контрольна)

Определяемое Перетворення Типа

Приведенная у вступі реалізація комплексних чисел занадто обмежена, щоб він влаштовувала когось, тому її потрібно розширити. Це в основному повторенням описаних вище методів.

Например:

class complex {.

double re, im;

public:

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

friend complex operator+(complex, complex);

friend complex operator+(complex, double);

friend complex operator+(double, complex);

friend complex operator-(complex, complex);

friend complex operator-(complex, double);

friend complex operator-(double, complex);

complex operator-() // унарный ;

friend complex operator*(complex, complex);

friend complex operator*(complex, double);

friend complex operator*(double, complex);

// …

};

Теперь, маючи опис complex, ми можемо написати:

void f ().

{.

complex a (1,1), b (2,2), c (3,3), d (4,4), e (5,5);

a = -b-c;

b = c*2.0*c;

з = (d+e)*a;

}.

Но писати функцію кожному за поєднання complex і double, як це робилося вище для operator+(), нестерпно нудно. З іншого боку, близькі до реальності кошти комплексної арифметики мають надавати по меншою мірою дюжину таких функцій; подивіться, наприклад, на той тип complex.

Конструкторы.

Альтернативу використанню кількох функцій (перевантажених) становить опис конструктора, котрий за заданому double створює complex.

Например:

class complex {.

// …

complex (double r) { re=r; im=0; }.

};

Конструктор, вимагає лише одне параметр, необов’язково викликати явно:

complex z1 = complex (23);

complex z2 = 23;

И z1, і z2 будуть инициализированы викликом complex (23).

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

Например, клас complex можна було б описати так:

class complex {.

double re, im;

public:

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

friend complex operator+(complex, complex);

friend complex operator*(complex, complex);

};

и дії, у яких входитимуть перемінні complex і цілі константи, заходилися б припустимі. Ціла константа буде інтерпретуватися як complex з травня нульової мнимої частиною. Наприклад, a=b*2 означає:

a=operator*(b, complex (double (2), double (0))).

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

Объект, сконструйований з допомогою явного чи неявного виклику конструктора, є автоматичним і загине за першої можливості, зазвичай відразу після оператора, коли він створили.

Операции Перетворення.

Использование конструктора для завдання перетворення типу є зручним, однак має слідства, які можуть бути нежелательными:

Не то, можливо неявного перетворення з певного користувачем типу в основний тип (оскільки основні типи є класами);

Невозможно поставити перетворення з нових типів в старий, не змінюючи опис старого; і.

Невозможно мати конструктор з однією параметром, які мають у своїй перетворення.

Последнее перестав бути серйозними проблемами, і з першими двома можна впоратися, визначивши для вихідного типу операцію перетворення. Функція член X: operator T (), де T — ім'я типу, визначає перетворення з X в T. Наприклад, можна визначити тип tiny (малюсінький), що мати значення буде в діапазоні 0…63, але вільний поєднуватися в цілими в арифметичних операціях:

class tiny {.

char v;

int assign (int i).

{ return v = (i&~63)? (error («помилка діапазону »), 0): і; }.

public:

tiny (int і) { assign (i); }.

tiny (tiny& і) { v = t. v; }.

int operator=(tiny& і) { return v = t. v; }.

int operator=(int і) { return assign (i); }.

operator int () { return v; }.

}.

Диапазон значення перевіряється завжди, коли tiny инициализируется int, і завжди, коли йому присвоюється int. Одне tiny може присвоюватися іншому без перевірки діапазону. Щоб дозволити виконувати над перемінними tiny звичайні цілі операції, визначається tiny: operator int (), неявний перетворення з int в tiny. Завжди, як у місці, де потрібно int, з’являється tiny, використовується відповідне йому int.

Например:

void main ().

{.

tiny c1 = 2;

tiny c2 = 62;

tiny c3 = c2 — c1; // c3 = 60.

tiny c4 = c3; // немає перевірки діапазону (необязательна).

int і = c1 + c2; // і = 64.

c1 = c2 + 2 * c1; // помилка діапазону: c1 = 0 (а чи не 66).

c2 = c1 -і; // помилка діапазону: c2 = 0.

c3 = c2; // немає перевірки діапазону (необязательна).

}.

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

Другое застосування визначених операцій перетворення — це типи, які дають нестандартні уявлення чисел (арифметика по підставі 100, арифметика з фіксованою точкою, двоично-десятичное подання, і т.п.). У цьому зазвичай переопределяются таких операцій, як + і *.

Функции перетворення виявляються особливо корисними для роботи з структурами даних, коли читання (реалізоване з допомогою операції перетворення) тривіально, тоді як присвоювання і ініціалізація помітно складніші.

Типы istream і ostream спираються на функцію перетворення, щоб зробити можливими такі оператори, як while (cin>>x) cout<>x вище повертає istream&. Це значення неявно перетвориться до значенням, яке вказує стан cin, а потім уже це значення може перевірятися оператором while. Проте визначати перетворення з нього типу на другий отже у своїй втрачається інформація, звичайно стоїть.

Неоднозначности.

Присваивание об'єкту (чи ініціалізація об'єкта) класу X є допустимим, якщо чи присваиваемое значення є X, чи існує єдине перетворення присваиваемого значення тип X.

В окремих випадках значення потрібного типу може сконструироваться з допомогою кількох застосувань конструкторів чи операцій перетворення. Це має робитися явно; допустимий лише рівня неявних перетворень, певних користувачем. Іноді значення потрібного типу може бути сконструйоване більш як єдиним чином. Такі випадки вже є неприпустимими.

Например:

class x { /* … */ x (int); x (char*); };

class y { /* … */ y (int); };

class z { /* … */ z (x); };

overload f;

x f (x);

y f (y);

z g (z);

f (1); // неприпустимо: неоднозначність f (x (1)) чи f (y (1)).

f (x (1));

f (y (1));

g («asdf »); // неприпустимо: g (z (x («asdf »))) не пробуется.

g (z («asdf »));

Определенные користувачем перетворення розглядаються в тому разі, якщо них виклик дозволити не можна.

Например:

class x { /* … */ x (int); }.

overload h (double), h (x);

h (1);

Вызов міг бути проінтерпретований чи як h (double (1)), чи як h (x (1)), був би неприпустимий за правилом одиничності. Але й одна інтерпретація використовує лише стандартне перетворення і її буде обрано за правилами. Правила перетворення є ні найбільш простими для реалізації і документації, ні найбільш загальними з тих, які можна було б розробити. Візьмемо вимога одиничності перетворення. Більше загальний підхід дозволив би компілятору застосовувати будь-яке перетворення, що він зможе знайти; в такий спосіб, непотрібно б розцінювати все можливі перетворення до того, як оголосити вираз допустимим. На жаль, це означала б, що зміст програми залежить від цього, яке перетворення було знайдено. Через війну сенс програми якось залежав від порядку описи перетворення. Оскільки часто перебувають у різних вихідних файлах (написаних різними людьми), сенс програми залежатиме від порядку компонування цих частин разом. Є інший варіант — заборонити все неявні перетворення. Немає нічого простіше, але таке правило призведе або до неэлегантным користувальницьким інтерфейсам, або до бурхливому зростанню перевантажених функцій, як це було попередньому розділі з complex.

Самый загальний підхід враховував б весь інформацію про типах і розглядав б, усе можливі перетворення. Наприклад, якщо використовувати попереднє опис, можна було б обробити aa=f (1), оскільки тип aa визначає одиничність тлумачення. Якщо aa є x, то єдине, дає внаслідок x, потрібного присвоюванням, — це f (x (1)), і якщо aa — це y, то натомість використовуватиметься f (y (1)). Найбільш загальний підхід впорався і з g («asdf »), оскільки єдиною інтерпретацією цього може бути g (z (x («asdf »))). Складність цього підходу у цьому, що він потребує розширеного аналізу всього висловлювання у тому, щоб визначити інтерпретацію кожну операцію і виклику функції. Це спричинить різке до уповільнення компіляції, і навіть до що викликають подив інтерпретаціям і повідомленням помилки, якщо компілятор розгляне перетворення, певні в бібліотеках тощо. За такого підходу компілятор прийматиме до уваги більше, ніж, як очікувалося, знає що пише програму програміст!

Список литературы

Для підготовки даної роботи було використані матеріали із російського сайту internet.

Показати весь текст
Заповнити форму поточною роботою