|
Программирование >> Оптимизация возвращаемого значения
указателя на объект const к указателю на объект, не являющийся const (то есть меняющим только атрибут const объекта), и приведением указателя на объект базового класса к указателю на объект производного класса (то есть приведение типа, которое полностью меняет тип указателя). Традиционное приведение типа в стиле языка С не различает эти два сл5ая (и неудивительно - приведение типов в стиле языка С было разработано для С, а не для С++). Вторая проблема с приведением типов заключается в том, что cnjan его применения трудно обнаружить. Синтаксически приведение типов состоит всего-навсего из пары скобок и идентификатора, а скобки и идентификаторы используются в С++ повсеместно. Таким образом, нелегко ответить даже на основной вопрос: Использует ли программа приведение типов? . Это происходит потому, что человеческий глаз не всегда замечает код приведения типов, а такие утилиты, как grep, не могут отличить его от других, синтаксически схожих, конструкций. Чтобы преодолеть недостатки приведения типов в стиле языка С, в язык С++ введены четыре новых оператора приведения типов: static cast, const cast, dynamic cast и reinterpret cast. Для большинства задач программист должен знать только, что там, где он привык писать (type) expression теперь следует писать static cast<type>(expression) Допустим, вам необходимо привести выражение типа int к типу double, чтобы получить число с плавающей точкой в результате вычисления целочисленного выражения. Используя приведение типов в стиле языка С, это можно было сделать следующим образом: int firstNumber,secondNumber; double result = ((double)firstNumber)/secondNumber; С новыми операторами приведения типа это делается так: double result = static cast<double>(firstNumber)/secondNumber; Теперь у нас есть приведение типов, которое легко обнаружат как человеческий глаз, так и программы. Оператор static cast обладает теми же возможностями, что и приведение типов общего назначения в стиле языка С. На него налагаются аналогичные ограничения. Например, таюке как и в языке С, с помощью static cast вы не можете преобразовать переменную типа struct в int или переменную типа double в указатель. Более того, с помощью оператора static cast нельзя убрать атрибут const в выражении, для этого служит специальный оператор const cast. Другие операторы приведения типов, введенные в С++, используются для более узкого круга задач. Оператор const cast предназначен для работы с атрибутами const и volatile в выражениях. Используя оператор const cast, вы подчеркиваете (как для человека, так и для компьютера), что собираетесь только изменить атрибут const или volatile какого-либо объекта. Это значение оператора поддерживают и компиляторы. Если попытаться использовать оператор const cast для других задач, отличных от изменения атрибутов const или volatile, то такое приведение типов будет отвергнуто. Вот некоторые примеры: class Widget { ... } ; class SpecialWidget: public Widget{ voidupdate(SpecialWidget *psw); SpecialWidget sw; const SpecialWidget& csw = sw; . . . } ; swHe const объект, но csw ссылается на него, / / как на cons t объект. update(&csw) ; Ошибка!Нельзя передавать const указатель SpecialWidget* функции,которая принимает указатель SpecialWidget*. update{const cast<SpecialWidget*>(Sccsw)); Нормально, атрибут const у &CSW / / удален в результате преобразования типа (иcswиswмoгyтбытьизмeнeны втeлeфyнкцииupdate). update{{SpecialWidget*)&csw); Widget *pw = new SpecialWidget-; update(pw); / / To же самое, но используя / / более трудное для обнаружения / / преобразование типа в стиле языкаС. Ошибка! pwHMeeTTnnWidget*, / / а функция update принимает аргумент типа SpecialWidget*. update{const cast<SpecialWidget*>{pw)); Ошибка!Операторconst cast можно использовать только для изменения атрибутов const илиvolatile инельзя применять для приведения наследования. В настоящее время оператор const cast чаще всего используется для изменения атрибута const. Второй специализированный оператор - dynamic cast - для безопасного приведения типа между уровнями иерархии наследования. Это означает, что оператор dYnamic cast позволяет приводить указатели или ссылки на объекты базового класса к указателям или ссылкам на объекты производных или дочерних классов таким образом, чтобы можно было определить, была ли попытка приведения типа успешной*. В результате неудачной попытки возвращается нулевой указатель (при преобразовании указателей) или возникает исключение (при преобразовании ссылок): widget *pw; update(dYnamic cast<SpecialWidget*>(pw)); Нормально, функции update передаетсяуказатель / / на объект класса SpecialWidget, еслирндействительноуказывает на этот объект, в противном случае передается нулевой указатель. voidupdateViaRef(SpecialWidget&rsw); updateViaRef{dynamic cast<SpecialWidget&>{*pw)); Нормально, передача функции / / updateViaRef ссылки на объект классаSpecialWidget, еслирк действительно указывает на этот объект, в противномслучае возникает исключение. Применение операторов dynamic cast ограничено возможностью навигации по иерархии наследования. Операторы нельзя использовать для приведения типов, не имеющих виртуальных функций (см. также правило 24), или для работы с атрибутом const: intfirstNumber,secondNumber; double result= dynamic cast<double>(firstNumber)/secondNumber; Ошибка! int не имеет виртуальных функций. const SpecialWidget sw; update{dynamic cast<SpecialWidget*>{&sw)); Ошибка! dynamic cast не может работать с атрибутом cons t. Если вы хотите выполнить преобразование ненаследуемых типов, то Л5ше всего подойдет оператор static cast. Чтобы удалить атрибут const, всегда применяется оператор const cast. Последний из четырех новых операторов - оператор reinterpret cast. Он используется для приведения типов в тех случаях, когда результат приведения почти всегда зависит от реализации. Из-за этого переносимость операторов reinterpret cast существенно ограничена. * Оператор dynamic cast всегда используется для того, чтобы найти начало памяти, занимаемой объектом. Подробнее об этом рассказано в правиле 27.
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |