|
Программирование >> Операторы преобразования типа
Новые операторы преобразования типа Чтобы профаммисты могли более четко выразить смысл явного преобразования типа с одним аргументом, в стандарт были воючены четыре новых оператора. О static cast Оператор преобразует значение на логическом уровне. Считайте, что он создает временный объект, который затем инициализируется преобразуемыми данными. Преобразование разрешено только при наличии преобразования типа, определенного либо по умолчанию, либо явно. Пример: float х: cout static cast<int>(x): Вывод х в формате int fCstatlc cast<string>( hello )): Функция fO вызывается для string. а не для char* О dynamic ca5t Оператор позволяет привести полиморфный тип к настоящему статическому типу. Это единственное преобразование типа, которое проверяется на стадии выполнения программы; следовательно, оно может использоваться для проверки типов полиморфных значений. Пример: class Car: Абстрактный базовый класс (содержит хотя бы одну чисто виртуальную функцию) class Cabriolet : public Car { class Limousine i public Car { void f(Car* cp) { Cabriolet* p = dynamic cast<Cabriolet*>(cp): If (p == NULL) { p не указывает на объект типа Cabriolet В данном примере в функции f() определены специальные действия для тех объектов, которые не относятся к настояп1ему статическому типу Cabriolet Если аргумент является ссылкой, а преобразование типа завершается неудачей, dynamic cast генерирует исключение bad cast (см. с. 43). Помните, что с точки зрения проектирования при работе с полиморфными типами всегда лучше избегать выбора действий в зависимости от фактического типа. О const cast Оператор создает пли отменяет атрибут константности типа. Кроме того, допускается отмена атрибута volatile. Все остальные модификации типа не разрешаются. О reinterpret cast Поведение этого оператора определяется реализацией. Он может (хотя и не обязан) повторно интерпретировать биты, из которых состоит величина Обычно применение этого преобразования затрудняет переносимость программы. Перечисленные операторы заменяют старую методику преобразования типов с использованием круглых скобок. К преимуществам нового способа можно отнести то, что он более наглядно выражает намерения программиста при преобразовании. Старый синтаксис применялся во всех рассмотренных случаях, кроме dynamlc cast, поэтому, встретив этот оператор в программе, трудно было сразу понять смысл преобразования. Новые операторы также снабжают компилятор дополнительной информацией о причинах преобразования и помогают выявлять ошибки, если преобразование выходит за границы положенного. Обратите внимание - новые операторы преобразования типа определены только для одного аргумента. Рассмотрим следующий пример: static cdSt<Fract1on>(l5.lOO) Ошибка: создается Fraction С100) Команда работает совсем не так, как можно было бы ожидать. Вместо того чтобы инициализировать врсмеьптый объект дроби с числителем 15 и знаменателем 100, она инициализирует временный объект с единственным значением 100. Запятая в данном случае не является разделителем аргументов, а интерпретируется как оператор, который объединяет два выражения и возвращает второе из них. Правильным способом преобразования величин 15 и 100 в дробь по-прежнему остается следующая команда: Fractlon(15.100) Правильно, создает FractionClB.lOO) Инициализация константных статических членов класса в новом варианте языка стало возможным инициализировать целочисленные константные статические переменные внутри класса. В частности, это может быть удобно при использовании константы в контексте класса после инициализации. Пример: class MyClass { static const int num = 100; int elemsEnum]; При этом для константных статических членов, инициализируемых внутри определения класса, все равно приходится резервировать память: const int MyClass::num: Инициализация не выполняется Определение main Нужно также прояснить очень важный и часто неверно понимаемый аспект базового языка, а именно правильность функции main(). Согласно стандарту С++, переносимыми являются только два определения main(): int mainC) int mainCint argc. char* argv[]) { Здесь argv (массив аргументов командной строки) также может определяться с типом char**. Еще обратите внимание на обязательное указание типа возвращаемого значения int, поскольку подстановка int по умолчанию считается нежелательной. Функция main() может (хотя и не обязана) завершаться командой return. В отличие от С в языке С++ main() по умолчанию завершается командой return О Из этого следует, что любая программа, в которой выход иэ main() происходит без команды return, завершается успешно (любое значение, отличное от О, свидетельствует о нестандартном завершении). По этой причине в примерах, приводимых в книге, команда return в конце main() отсутствует. Учтите, что некоторые компиляторы могут выдавать предупреждение и даже сообщение об ошибке. Что ж, они просто отстали от жизни. Сложность алгоритмов в некоторых компонентах стандартной библиотеки С++ (и особенно в STL) первостепенное внимание уделяется скорости работы алгоритмов и функций классов. По этой причине в стандарт включены требования к их сложности -. Специалисты по информатике применяют специальную систему обозначений для сравнения относительной сложности алгоритмов. По этому критерию можно быстро оценить относительное время работы алгоритма, а также сравнить алгоритмы на качественном уровне. Эта система обозначений называется 0-записъю. О-запись выражает вр>емя работы алгоритма как функцию от объема входных данных п. Например, если вр>емя работы алгоритма прямо пропорционально количеству элементов (удвоение объема входных данных в два раза зшеличивает время работы), сложность алгоритма записывается в виде 0(л). Если время работы не зависит от объема входных данных, алгоритм обладает сложностью 0(1). В табл. 2.1 перечислены типичные варианты сложности и соответствующая им О-запись.
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |