6.3.2 Операции Преобразования
6.3.2 Операции Преобразования
Использование конструктора для задания преобразования типа является удобным, но имеет следствия, которые могут окзаться нежелательными:
1. Не может быть неявного преобразования из определеного пользователем типа в основной тип (поскольку осноные типы не являются классами)
2. Невозможно задать преобразование из нового типа в старый, не изменяя описание старого
3. Невозможно иметь конструктор с одним параметром, не имея при этом преобразования.
Последнее не является серьезной проблемой, а с первыми двумя можно справиться, определив для исходного типа операцию преобразования. Функция член X::operator T(), где T – имя тпа, определяет преобразование из X в T. Например, можно опрделить тип tiny (крошечный), который может иметь значение только в диапазоне 0...63, но все равно может свободно сочтаться в целыми в арифметических операциях:
class tiny (* char v; int assign(int i) (*return v=(i amp;~63) ? (error(«ошибка диапазона»),0):i;*) public: tiny(int i) (* assign(i); *) tiny(tiny amp; i) (* v = t.v; *) int operator=(tiny amp; i) (* return v = t.v; *) int operator=(int i) (* return assign(i); *) operator int() (* return v; *) *)
Диапазон значения проверяется всегда, когда tiny иницилизируется int, и всегда, когда ему присваивается int. Одно tiny может присваиваться другому без проверки диапазона. Чтбы разрешить выполнять над переменными tiny обычные целые операции, определяется tiny::operator int(), неявное преобрзование из tiny в int. Всегда, когда в том месте, где требется 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;
Действие ввода cin»»x выше возвращает istream amp;. Это знчение неявно преобразуется к значению, которое указывает сотояние cin, а уже это значение может проверяться оператором while (см. #8.4.2). Однако определять преобразование из оного типа в другой так, что при этом теряется информация, обычно не стоит.