ПЕРЕЛІК ДИСЦИПЛІН:
  • Адміністративне право
  • Арбітражний процес
  • Архітектура
  • Астрологія
  • Астрономія
  • Банківська справа
  • Безпека життєдіяльності
  • Біографії
  • Біологія
  • Біологія і хімія
  • Ботаніка та сільське гос-во
  • Бухгалтерський облік і аудит
  • Валютні відносини
  • Ветеринарія
  • Військова кафедра
  • Географія
  • Геодезія
  • Геологія
  • Етика
  • Держава і право
  • Цивільне право і процес
  • Діловодство
  • Гроші та кредит
  • Природничі науки
  • Журналістика
  • Екологія
  • Видавнича справа та поліграфія
  • Інвестиції
  • Іноземна мова
  • Інформатика
  • Інформатика, програмування
  • Юрист по наследству
  • Історичні особистості
  • Історія
  • Історія техніки
  • Кибернетика
  • Комунікації і зв'язок
  • Комп'ютерні науки
  • Косметологія
  • Короткий зміст творів
  • Криміналістика
  • Кримінологія
  • Криптология
  • Кулінарія
  • Культура і мистецтво
  • Культурологія
  • Російська література
  • Література і російська мова
  • Логіка
  • Логістика
  • Маркетинг
  • Математика
  • Медицина, здоров'я
  • Медичні науки
  • Міжнародне публічне право
  • Міжнародне приватне право
  • Міжнародні відносини
  • Менеджмент
  • Металургія
  • Москвоведение
  • Мовознавство
  • Музика
  • Муніципальне право
  • Податки, оподаткування
  •  
    Бесплатные рефераты
     

     

     

     

     

     

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

     

    Інформатика, програмування

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

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

    Наприклад:

    class complex (

    double re, im;

    public:

    complex (double r, double i) (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;

    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 i = 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): i;)

    public:

    tiny (int i) (assign (i);)

    tiny (tiny & i) (v = t.v;)

    int operator = (tiny & i) (return v = t.v;)

    int operator = (int i) (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 i = c1 + c2;// i = 64

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

    c2 = c1-i;// помилка діапазону: 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 "))). Складність цього підходу в тому, що він вимагає розширеного аналізу всього вирази для того, щоб визначити інтерпретацію кожної операції та виклику функції. Це призведе до уповільнення компіляції, а також до викликає здивування інтерпретацій і повідомлень про помилки, якщо компілятор розгляне перетворення, визначені у бібліотеках і т.п. При такому підході компілятор буде брати до уваги більше, чому, як можна очікувати, знає що пише програму програміст!

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

    Для підготовки даної роботи були використані матеріали з сайту http://www.realcoding.net

         
     
         
    Реферат Банк
     
    Рефераты
     
    Бесплатные рефераты
     

     

     

     

     

     

     

     
     
     
      Все права защищены. Reff.net.ua - українські реферати ! DMCA.com Protection Status