|
Программирование >> Операторы преобразования типа
Неявные преобразования типов Конструкторы снециализированных версий для типов float double и long double спроектированы так, чтобы безопасные преобразования типов (например, complex<float> в complex<double>) могли выполняться неявно, а потенциально рискованные преобразования (например, complex<long double> в complex<double>) были явными (см. с. 521): std std std std std std :complex<float> cf: :complex<double> cd; :complex<long doub1e> eld: complex<double> cdl = cf: OK: безопасное преобразование complex<double> cd2 = eld: ОШИБКА: нет неявного преобразования complex<double> cd3(cld); OK: явное преобразование He существует конструкторов, создающих комплексное число по другим комплексным типам. В частности, нельзя преобразовать complex с целым типом в complex с типом float, double или long double. Впрочем, преобразования можно выполнять при передаче вещественной и мнимой частей в отдельных аргументах: std::complex<double> cd: std::complex<int> ci: std std std complex<double> cd4 = ci; ОШИБКА: небезопасное преобразование complex<double> cd5(ci): ОШИБКА: нет явного преобразования complex<double> cd6(c1.real О.ci.imagO): OK К сожалению, операторы присваивания позволяют выполнять небезопасные преобразования. Они определены в виде шаблонов для всех типов, поэтому присваивание допустимо для любых комплексных типов (при возможности преобразования типа значения): std std std complex<double> cd: complex<long double> eld cofnplex<int> ci: cd = ci; OK cd = eld: OK Эта проблема также относится к функциям ро1аг() и conj(). Например, следующая запись работает нормально; std::complex<float> c2(std::ро1аг(4.2.0.75)): ОК С другой стороны, запись со знаком = не работает: std::complex<float> с2 = std::ро1аг(4.2.0.75): ОШИБКА Вероятно, тот факт, что конструкторы допускают только безопасные неявные преобразования типов, тогда как операции присваивания допускают любые неявные преобразования, является ошибкой стандарта. abs(c) Возвращает модуль с (/с геа1() + с imag()) norm(c) Возвращает квадрат модуля с (c.real()+c.imag()) arg(c) Возвращает фазовый угол в полярном представлении с (ф); эквивалент atan2(c.imag(),c.real()) Функции геа1() и imag() позволяют только прочитать значения вещественной и мнимой частей. Чтобы изменить любую из частей комплексного числа, необходимо присвоить ему новое значение. Например, следующая команда присваивает мнимой части с значение 3.7: std::complex<double> с; с = std: :coniplex<double>(c.real().3.7); Операции сравнения Из всех операций сравнения для комплексных чисел определены только проверки на равенство и на неравенство (табл. 12.4). Операторы == и != определены как глобальные функции, поэтому один из операндов может быть скалярной величиной. В этом случае операнд интерпретируется как вещественная часть, а мнимой части комплексного числа присваивается значение по умолчанию для данного типа (обычно 0). Другие операции сравнения (например, с оператором < и т. д.) для класса complex не определены. Хотя в принципе для комплексных чисел можно определить порядок сортировки, результат получается недостаточно интуитивным и не приносит особой практической пользы. Например, сравнивать комплексные числа Между следующими двумя фрагментами существует нетривиальное различие: X х: Y у(х): Явное преобразование X х: Y у = х: Неявное преобразование Дело в том, что выражение std::polar(4.2,0.75) создает временный объект complex<double>, а неявное преобразование из complex<double> в complex<float> не определено Доступ к данным в табл. 12.3 перечислены функции получения атрибутов комплексных чисел. Таблица 12.3. Операции доступа к данным класса complexo Выражение Описание c.realQ Возвращает значение вещественной части (функция класса) геа1(с) Возвращает эначение вещественной части (глобальная функция) c.lmagO Возвращает значение мнимой части (функция класса) imag(c) Возвращает эначение мнимой части (глобальная функция) на основании модулей бессмысленно, поскольку два разных комплексных числа (например, 1 и -1) могут иметь одинаковые модули. Конечно, можно изобрести специальный критерий сортировки, например, для двух комплексных чисел с1 и с2 считать, что с1<с2 при выполнении условия с11<1с2, а в случае совпадения модулей - при выполнении условия arg(cl)<arg(c2). Тем не менее такие искусственные критерии не обладают математическим смыслом Таблица 12.4. Операции сравнения для класса complexo Выражение Описание с1 == с2 Проверка на равенство с1 и с2 (С1.геа1()==:с2.геа1() && cl.imag()==c2.imag()) с1.7 Проверка на равенство с1 и 1.7 (с1.геа1()==1.7 8t&cl.imag()==0.0) 1.7 == с Проверка на равенство 1.7 и с (с1.геа10==1.7 8t& cl.imag()==0.0) cl != с2 Проверка на неравенство с1 и с2 (с1.геа1()!=с2.геа1() cl.innag()!=c2.imag()) с != 1.7 Проверка на неравенство с1 и 1.7 tcl.realQ!=1.7 cl.innagONO.O) 1.7 != с Проверка на неравенство 1.7 и с (с1.геаК)!=1.7 cl.innag()!=0.0) Из этого следует, что тип complex не может быть типом элементов ассоциативных контейнеров (без определения пользовательского критерия сортировки). Дело в том, что для сортировки элементов по умолчанию ассоциативные контейнеры используют объект функции lesso, который вызьгоает оператор < (см. с. 143). Определение пользовательского оператора < позволяет сортировать комплексные числа и использовать их в ассоциативных контейнерах. Будьте внимательны и не нарушайте стандартное пространство имен. Пример: template <class Т> bool operator< (const std::complex<T>& cl. const std::complex<T>& c2) return std::abs(cl)<std::abs(c2) П (std::abs(cl)==std::abs(c2) && std::arg(cl)<std::arg(c2)); Арифметические операции Для комплексных чисел определены четыре базовые арифметические операции, а также операции изменения знака (табл. 12.5). Таблица 12.5. Арифметические операции класса complexo
Спасибо Дэвиду Вандеворду (David Vandevoorde) за это пояснение.
|
© 2006 - 2025 pmbk.ru. Генерация страницы: 0.001
При копировании материалов приветствуются ссылки. |