Г. Шилтд - Самоучитель C++ (DJVU) (1114955), страница 55
Текст из файла (страница 55)
Это безопасней, поскольку инструкция 11 с помощью оператора 1уреН проверяет правильность выполнения операции еще до того, как она действительно происходит. Тем не менее для этого есть более короткий путь. Оператор $уреЫ с инструкцией К можно заменить оператором ()уваппс сак1: др = с1упашз.с саае<Г)еттчес) "> (Ьр) Поскольку оператор йуаавис саз$ заканчивается успешно только в том случае, если объект, к которому применяется операция приведения типов, является либо объектом целевого типа, либо объектом производного от целевого типа, то после выполнения приведенной выше инструкции указатель йр будет либо нулевым, либо указателем на объект типа Вег(чей.
Таким образом, оператор йупапмс сав1 успешно завершается только при правильном приведении типов, а это значит, что в определенных ситуациях он может упростить логику программы. 1, В следующей программе продемонстрировано использование оператора йупаш1с саа$: // Использование оператора с(упаш1.с сакс ()Ъпстпе(е <Хоастеаш> ик~пп патпекрасе ась с1акк Ваке ( реь1вс: ч(ттца1 чоЫ Г() ( сои1 « "Внутри класса Ваке"'~п; )' с1акк Репчес(: рпЬИс Ваке роь|ъс: чон( Г() ( соо( « "Внутри класса Эек~чес("Хп) ) )п( паап () ( Веке *Ьр, Ь оЬ; Юеттчее *с1р~ Й оъ; Глана 12.
Дииаиичесяая идвнтификациии приведение типов бр = аупаш1с саяг<0ег1уес( *> (йб оЬ)) И(с(р) ( сопГ « "Тип Бег1чес( * к типу ()ег1чес( * приведен успешно'~п"; с)р->г (): ) е1яе сопя « "Ошнбка~п"; сонг « епс)1; Ьр с)упаш1с сваг<Вазе *> (йс( оЬ); 1~(Ьр) ( соил « "Тйп ()егЫес) * к типу Ваяе * приведен усавшно~П"; Ьр->Г(); ) е1яе сонг « "Ошибка~п") соус « еп61; Ьр = йупаш1с савГ<Ваае *> (йЬ оЬ); 1~(Ьр) ( сопГ « "Тип Ваяе * к типу Ваяе * приведен успешнс~п"; Ьр->й() ( ) е1яе сонг « "Ошибка~п"," сопл « епб1; бр = бупаш1с савг<Оег1чес *> (йЬ оЬ); 11' (с)р) ( сопб « "Ошибка~п"; е1яе сопГ « "Тип Ваяе " к типу Рег1чеб * не приведен~в"; сопл « епб1у Ьр = й<( оЬ; ~/ Ьр указывает на объект типа ВегЫед бр = с(упатпйс саяГ<Вег1леб *> (ЬР); Ы (бр) ( сопс « "Указатет Ьр к типу ))ег1;ес( * приведен успешно'~п" << "поскольку Ьр в действительности указывает~п" << "на объвкт типа ))ег1лесР,п"; ср->Г(); е1яе собак « нбшибка~п"й сопГ « епо1; Ьр = йЬ оЬ; О Ьр указывает на объект типа Ваяе бр = бупаш1с савг<))егЫтес) ~> (Ьр); 11(бр) сопГ « "Ошибка~п"( Самоучитель С++ е1ле 1 сопл « "указатель ьр к тиггу Регтуеб * не приведен~в" « "поскольку Ьр в действительности указываете' « "на объект типа Вазе~в"; сонг « егб1; бр = 6б оЬ! // бр указывает на объект типа Регтчеб Ьр = бупаш1с свай<Вале "> (бр) ~ з.й'(Ьр) Е сопс « "Указатель ар к типу Вазе * приведен успешно~в" « Ьр-)~~1," е1ье сопб « "Ошибка'и*'; геРпгп О; Программа выводит на экран следуюшую информацию: тип Регтлеб * к типу Регтуеб * приведен успешно Внутри класса Регтчеб Тип Регштеб * к типу Вазе * приведен успешно Внутри класса Рег1чеб тиг Вале * к типу Вале * приведен успешно Внутри класса Вазе Тип Вале * к типу Рег1; еб * не приведен Указатель Ьр к типу Регтуеб " приведен успешно поскольку Ьр в действительности указывает на объект типа Регктеб Внутри класса Рег1~еб Указатель Ьр к типу Регауеб * не приведен поскольку Ьр в действительности указывает на объект типа Вале Указатель бр к типу Вале * призадев успешно Внутри класса Регачеб 2.
В следующем примере показано, как оператор ~уреЫ можно заменить опера-. Р аУ 1е .С. l* использование оператора бупатп1с сааб для заменя оператора гуретб */ $1пс1пбе <1оз~леат> 373 Глава 22. динамическая идентибикация и приведение ТИПОВ () 1пс1ы<)е <гуре1п1о> инула патеярасе вГс)) с1ава Ваяе ( риЬ11с".
ч1ггыа1 чоЫ Й() ); с1аяя Рег1чео: риЬ11с Ваяе рпЬ11с: чоЫ йег1чес)Оп1у() соня « »Это объект класса Рег1чес)"'~п; 1пс таа1п() 1 Ване *Ьр, Ь оЬ; Рег1чес) *ор, с1 оЬ; // аа*»*ах**ха»*»»+ааааа*а»»а»аа*Ф а* **ха а ха»»»*» использование оператора ГуреЬ2 // *ах*ах»*хаааа»хааа»ааххаха**хааа*****ха *» а»*а*»а»»» Ьр = аЬ оь; 1й(луре1с((хЬр) == ГуреЫ(Рег1чеФ ) йр = (Рег1чео *) Ьр; е)р->йег1~ едОи1у (); ) е1яе сонг « »тип Ваяе к типу Регучес) не приведен~в"т Ьр — йс( оЬ; 11(Гуреев (*Ьр) == Гуре1<((Рег1че<()) ( с(р =. (Рег1чео *) Ьр; ар->бег1чеаоп1у(); ) е1яе сонг « »Опкк)ка, приведение типов должно работать!~п"; // ** * * * ***+*+*** ха****а***а** аха» *** а *» а » * // использование оператора с)упаппс саяе х*** ***»*а***** ххах*ах»ххаааа*ха****а*а»ха*хххххх» Ьр= 3ЬоЬ; др = с)упав1с сая~<Рег1чеб х> (Ьр); 11(бр) <)р->с)ег1лес)Рп1у()," е)яе соус « »'.(ин Вазе к типу Рег1чей не приведенчп"; Ьр = йс) ОЬ7 йр = йупалаус саяс<Рег1»теа *> (Ьр); 374 Самоучитель С+.(' 1Т (с(р) ир->г)егдчег(оп1у () т е1ве соис « "Ошибка, приведение типов должно работать! 'хп" р гегигп О: Как видите, использование оператора Йушшйс сав$ делает проще логику приведения типа указателя базового класса к типу указателя производного класса.
После выполнения программы на экран будет выведена следующая информация: тип Вазе к типу Рег(чес( не приведен Это объект класса Рег1уед Тип Вазе к типу Рег(чег( не приведен Это объект класса Рег(уег( 3. Оператор дупаппс саа1, как и оператор $уре1е, можно использовать с классами-шаблонами. Например, в следующем примере представлен переработанный класс-шаблон из примера 5 раздела 12.1. Здесь тип объекта, возвращаемый функцией ~еце~а$огО, определяется с помощью оператора Йупашс еааФ.
// Использование оператора е)упапис савГ с шаблонами ((ъпс1иг(е <1оа1геахп> ()зпс1ш(е <свгд)(Ь> ()Тпс1ис(е <спаЕЬ> ()1пс1иг(е <суре1пго> иа)па пагпеврасе асс); Гегпр1а1е <с1аьв Т> с1аьв Кита ( риЫТс: Т х; 'г)ипх (Т 1) ( х 1; ) чтггиа1 Т аег ча1() ( веси"и Х) ) Сетр1аге <с1ааа т> с1авв Яс(иагу: риЫТс Иихп<Т> ( риЫ1с: яс)иагу(т 1): (чтпв<Т>(1) () 'г деТ па1() ( гесигп х*ху ) Сетр1а е <с1ааа т> с1ааа Бс)г гоос: риЬ11с Кшв<Т> риЫ3.с: вг(г гсов(Т 1): Ихпп<Т>(1) () Т де~ па1() Г гегигп ах(г~((г)оиЫе) х); Глава 12.
Динамическая идентификаций и приведение типов от класса Хшп объектов () ]п( па1п () Иота<с]опЬ1е> оЬ1 (10), *р1; Яс]пату<с]овЬ1е> оЬ2 (100.0], *рг; ЯЦк лоос<с]опЬ1е> оЬЗ(999.2), *РЗ( шл сои1 « "Генерируем несколько объектов~в"1 йол(1=0; 1<10; 1++) ( р1 депетабот ( ) ~ р2 = с]упат1с савт<яс]пату<с]ооЬ1е> *> (р1]; йй(р2) сорб « "Квадрат объекта: "у рЗ = с]упавшее сав1<Яс]т тоо1<с]оиЬ1е> *> (р1); 1Е(рЗ] совс « "Квадратный корень объекта: совс « "значение равно: " « р1->дев ча1 (); соля « епс11; гетитп 01 1.
Своими словами объясните назначение оператора 1]УййЫС СйЯ1. 2. Дан следующий Фрагмент программы. Покажите, как с помощью оператора дуййпйс Ей6$ сделать так, чтобы указатель р указывал на некоторый объект оЬ только в том случае, если объект оЬ является объектом типа Р2. с]аяя В ( у]гша] уо]с] 1П О ]1 Фабрика производных т]оза<с]оиЬ1е> *депега1ок ( зи11с)з(гапс](] % 2) саяе 0: гевнвп саяе 1: геблгп ) тебя тп ]](]01.; с]аяя 01: рнЬИс В ( уоЫ Е() (] ]1 пеи Яс]ааку<допЬ1е> (ганс] () Ф 100); пеи Яс]т лоос<с)овЬ1е> (ганс)() Ъ 100) ] Самоучитель С-н- 376 с(ааа 02: риЫ1с В ( чоЫ 3. Переделайте функцию та)в~) из раздела 12.1, упражнение 4 так, чтобы для запрещения вывода на экран объектов типа ХиПЯ)аре использовался не оператор (уреЫ, а оператор чуваш(с саа(. 4. Будет ли работоспособен следующий фрагмент программы в иерархии классов с базовым классом Мшп из примера 3 этого раздела? ((шп<.(пс> *Вр; вяньте<<(опь1е> ~Рр; // Ор = дупагп(с саа<<исл1<тп~» (вр~; 12.3.
Операторы сопзй сазй, гет1егрге1 саз1 и з1абс саз1 Хотя оператор Иупаппс савФ самый полезный из новых операторов приведения типов, кроме него программистам доступны еще три. Ниже представлены их основные формы: оопет. сап с<целевое вап> (лвревевве) (вщ>авенве) есаул.о саеФ<пепевов твп> (выражение) Здесь це/(ееай тип — это тип, которым должен стать тип параметра еьуаженис после выполнения операции приведения типов. Как правило. указанные операторы обеспечивают более безопасный и интуитивно понятный способ выполнения некоторых видов операций преобразования, чем оператор приведения типов, более характерный для языка С.
Оператор сопя( савФ при выполнении операции приведения типов используется для явной подмены атрибутов сова( (постоянный) и/или уо!а(1)е (переменный). Целевой тип должен совпадать с исходным типом, за исключением изменения его атрибутов сопв( или то1аЯе. Обычно с помощью оператора сопя( сая$ значение лишают атрибута сопв$ Оператор Ма((с сав( предназначен для выполнения операций приведения типов над объектами неполиморфных классов.
Например, его можно использовать для приведения типа указателя базового класса к типу указателя производного класса. Кроме этого, он подойдет и для выполнения любой Глава 12. Динамическая идентификация и приведение типов стандартной операции преобразования, но только не в динамическом режиме (т.
е. не во время выполнения программы). Оператор геЫегрге$ сав1 дает возможность преобразовать указатель одного типа в указатель совершенно другого типа. Он также позволяет приводить указатель к типу целого и целое к типу указателя.
Оператор ге1пгегрге1 спвГ следует использовать для выполнения операции приведения внутренне несовместимых типов указателей. Атрибута сопМ объект можно лишить только с помощью оператора сопв$ савг. С помощью оператора ((упаппс саМ, втабс савг или ге$пгегргес савг этого сделать нельзя. 1. В следующей программе демонстрируется использование оператора геш1егргег сав$. // Пример использования оператора ге(птегргет саят и(пс)нг(е с1овсгееза> из(пя пагпезрасе аМ; (п( пати () ( 1пг 1) с)заг *р = "Это строка"; // приведение типа указателя к типу иелого ге(п(егргет сая(<(п(> (р) ) сои « ге(игп О; В данной программе с помощью оператора ге(п1егрге$ саяФ указатель на строку превращен в целое.
Это фундаментальное преобразование типа и оно хорошо отражает возможности оператора геЫегргег савг. 2. В следующей программе демонстрируется оператор совами савг. // Пример использования оператора сопя( сазг ()зпс1ис(е <).светел> иа(пя патпезрасе а(д; уоиг "(сопас (п( *р) )пг 'ч; Самоучитель с ж 378 // преобразование тит.а лижает указатель р атрибута сопев — сопят савт<1пв ь> (р); *ч = 100; // теперь указатель ч может изменить объект тпб п4а1П() ( ьпс х = 99; соил « "Объект х перед вызовом функции равен: " « х « епб1; Х(ах); сопс « "Сбьект х после вызова функции равен: " « х « епб1; -есцтп 0; Ниже представлен результат выполнения программы: Объект х перед вызовом функции равен: 99 Объект х после вызова функции равен: 100 Как видите, несмотря на то что параметром функции Го задан постоянный указатель, вызов этой функции с объектом х в качестве параметра изменил значениеобъекта. Возможность снятия оператором сопев„оазт атрибута сопвт при выполнении операция приведения типов потенциально очень опасна.