Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Бичков - Основи сучасного програмування.doc
Скачиваний:
69
Добавлен:
07.03.2016
Размер:
2.67 Mб
Скачать

7.12.2. Перетворення типів

Програміст має сам подбати про перетворення типів при роботі з різнотипними даними, де використовуються його власні типи даних. Операції перетворення типів за умовчанням при роботі з типами користувача зазвичай не працюють. Виняток становить так зване неявне перетворення типів, про яке буде сказано далі. Для забезпечення роботи з різнотипними даними існує кілька підходів:

1. Використання перевантажених функцій з різними типами параметрів:

friend complex operator+(complex,complex);

friend complex operator+(complex,double);

………………..

complex b(2,2),c(3,3);

b=c+20+b;

2. Використання конструкторів, які виконують відповідні перетворення типів. Мається на увазі виклик відповідних конструкторів у ситуаціях, коли замість значення деякого типу за синтаксисом має бути об'єкт.

Розглянемо описаний вище клас string.

У рядках

string a="1234";

string b="4321";

відбувається, фактично, виклик відповідних конструкторів, а потім присвоєння екземплярам а та в відповідних абстрактних об'єктів. Аналогічні виклики відбуваються й у випадках, коли різнотипні дані зустрічаються в деяких арифметичних виразах. Наприклад:

class complex {

//...

complex(double f){re=f;im=0;}

};

Можна було б записати конструктор і так:

class complex {

//…

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

};

Тоді в main()-функції можемо записати:

complex a(1,2),b(3);

a=b+121;

В останньому рядку відбувається неявний виклик конструктора complex(121), а потім виконується перевантажена операція додавання для екземплярів класу complex. Якщо конструктор наведеного вище типу не визначений, то можемо в даній ситуації зробити так:

a=operator+(b,complex(double(121),double(0)));

Використання конструкторів має деякі недоліки:

1. Виникають труднощі з неявним перетворенням типу від типу користувача до основного.

2. Не може бути неявного перетворення від нового типу до старого без зміни старого.

Позначимо через Т ім'я типу, X – деякий клас, тоді функція-член

X::operator т();

здійснює перетворення типу з X на Т. Якщо ми використаємо описаний вище клас string та ініціалізуємо екземпляр класу

string myvalye="1234";,

то рядок long x=myvalue; буде помилковим, оскільки в класі не передбачено перетворення рядка на довге ціле.

Вихід з такої ситуації – перевантаження операції перетворення типу. У класі string необхідно описати функцію вигляду

operator long(){return atol(value);}

При роботі з різнотипними даними слід уникати можливих неоднозначностей. Розглянемо приклад:

class x{

public:

x(int){};

x(){};

};

class y {

public:

y(int){};

};

class z {

public:

z(x){};

z(y){};

};

main()

{

z f(1);

}

При оголошенні екземпляра класу z f(1) у функції main() виникає неоднозначність. Згідно з оголошенням параметром конструктора класу z має виступати екземпляр або класу x, або y. Оскільки тут стоїть одиниця й у класах є конструктори, що дозволяють здійснити перетворення від цілого до типу відповідного класу, то таке перетворення має бути здійснене. Однак у якому класі це відбудеться, якщо вони обидва містять відповідні конструктори? Компілятор відстежує такі неоднозначності.

Для оптимізації роботи програми як формальні параметри перевантажених операцій краще використовувати посилання:

class matrix {

double m [300][400];

public:

matrix (){};

friend matrix operator+(matrix &,matrix &);};

Це дозволить уникнути копіювання даних, що займають значний обсяг пам'яті, у стек.