Г. Шилтд - Самоучитель C++ (DJVU) (1114955), страница 12
Текст из файла (страница 12)
34, "Нес(къс)са" ); Смысл анонимных объединений в том и состоит, что они обеспечивают простой способ сообщить компилятору о необходимости разместить одну или несколько переменных в одной и той же области памяти. Исключая эту особенность, члены анонимного объединения больше ничем не отличаются от других переменных. Все те ограничения, которые накладываются на использование обычных объединений, применимы и к анонимным объединениям.
Кроме этого к ним добавлено еще несколько. Глобальное анонимное объединение должно быть объявлено как статическое. Анонимное объединение не может содержать закрытых членов. Имена членов анонимного объединения не должны конфликтовать с другими идентификаторами той же области видимости. с+- Самоучитель 88 асс1.яЬоы(); асс2.яЬоиО; те«итп О," Ниже представлена только что рассмотренная программа, но вместо структу- ры здесь используется класс: ()ъпс1пс(е <ъоя«теав> ««гпс1пае <ся«тгпо> пяъяо павеярасе я'сб с1аяя с1 «уре ооиЬ)е Ьа1апсе; сЬат паве(40]; рцЬ11с.' с1 «уре(с(оиЬ1е Ь, сЬа= *и); чоЫ яЬох (); с1 «уре::с1 «уре(с)опЬ1е Ь, сЬат *и) ( Ьа'апсе =- Ь; я««ору (пас«а, и); чоъс(с1 «уре:: яЬои() соп« « "имя:" « паве; соп«« ": Э" « Ьа1апсе; 11'(Ьа]апсе < О.
0) сои( « "**~"; сои( « "Хп"; 1п( ваъп () ( с1 «уре асс1(100.12, с1 «уре асс2(-12.34, " ТоЬпяоп" ); "Нес)«тсКя"); асс1. яЬох О ~ асс2.яЬое О; Отметьте, что, как уже говорилось, члены структуры по умолчанию являются открытыми. Для объявления закрытых членов необходимо использовать ключевое слово рпта1е. Кроме этого отметьте существенное отличие между структурами С и структурами С++.
В С++ имя тета становится также и законченным именем типа данных, которое можно использовать для объявления объектов. В С, чтобы имя тета стаю законченным именем типа данных, перед ним надо указывать ключевое слово а1гис1. 69 Глана Введение классы гетпгп О; () гпс1пс[е <1овггеа~п> пз(пя пагпезрасе зЫ; ипгоп Ь(ге ( Ь1сз (допЬ1е п); чей аЬои Ь1Гз(); г)оиЬ)е <); ппвгдпеб сЬаг с[з1вео1 (допЬ1е)); Ьусз::Ьггз (попЬ1еп) чогс[Ь1св:: аЬох Ьгсз() 1пг 1, 3; бог( 7' = з1геог (с[опЬ1е) — 1; 7' >= 0; 3 — ) сопл « "Двоижое представление байта" « 7' аког( 1 = 128; 1; 1 »= 1) 11(1 а с[ 7 ] ) сопл « "1"; е1ве сопл « "0"; сопл « "~п") 1пг пакп ( ) ( Ь1г оь(1551.агЭ) оЬ.зпои Ьггв(); гегпгп 0; Результат работы программы представление байта 7: 01000000 представление байта б: 10011111 представление байта 5: 00011111 представление байта 4: 01010000 представление байта 3: 11100101 Двоичное Двоичное Двоичное Двоичное Двоичное 2. Пример использования объединения для побайтного вывода значения типа йовЫе в двоичном представлении: 70 Самоучитель Двоичное представление байта 2: 01100000 Двоичное представление байта 1: 01000001 Двоичное представлежче байта 0; 1000:001 3.
Структуры и объединения могут иметь конструкторы и деструкторы. В следующем примере класс зЫуре переделан в структуру. В структуре имеются конструктор и деструктор. ()1пс1ибе <1озсгеав> ((1ПС1иС(Е <ся Ступу> ()1пс1ис)е <сяяс(11Ь> ия1по пап~еярасе ясФ яслнсс я'ьгяуре ( з Г лемуре (сЬат *рст); -зстсуре (); уоЫ знои[); рл1уа" е: с).ат ~р; 1пС 1еп; з~т~уре:: з~т~уре (сЬат *рсг) ( 1еп = зТт1еп(рТт); р = (сваг *) ша11ос(1еп + 1); ((<)р> сои « "Ошибка выделения памяти 1п" р ех1ь (1); астору(р, рпт) зсггуре:: -я~т~уре() ( сопя « "Освобождение памяти по адресу р~п"; Клее(р)) уоус( я~в~ура:: знои() ( сонь « р « "- длина: " « 1еп; соне « "1п"' 1пс шаше () ( яятлуре з1 ("Это проверка"), я2 ("Ине нравится С++") 7 Глава 2.
Введение классы а1.анен(); а2, аной (); гегпгп О; 4. В следующей программе для побайтного вывода на экран значения типа йоиЫе используется анонимное объединение. (Предполагается, что длина значения типа ()овЫе равна восьми байтам.) О Использование анонимного объединения (11пс1пс(е <1оаСгеал~> из(пд патезрасе з1с(; !П( гааза () цп(оп ( цпяяпед с(заг Ьусаа [81! дои(з(е ча1иа; ) г (гзт 1г ча(пе '= 859345.324; // побайтный вывод значения типа г(опЫе Хог (1=0; ((8; (ч-ч-) соиГ « (1пс) ЬуСеа(1) « гегпгп О; Обратите внимание, что доступ к переменным ча1ве и Ьу1ев осуществляется так, как если бы они были не частью объединения, а обычными переменными. Несмотря на то, что эти переменные объявлены как часть анонимного объединения, их имена находятся в той же области видимости, что и другие объявленные здесь локальные переменные.
Именно по этой причине член анонимного объединения не может иметь то же имя, что и любая переменная в данной области видимости. 1, Перепишите класс а1ас1, представленный в разделе 2.1, чтобы вместо класса использовалась структура. 2. Используйте объединение, чтобы поменять местами старший и младший байты целого (предполагается 16-битное целое; если ваш компьютер использует 32-битное целое, то меняйте местами байты типа а)юг1 1п1).
3. Объясните, что такое анонимное объединение и чем оно отличается от нор- мального объединения. Самоучитель 2.6. Встраиваемые функции Перед тем как продолжить исследование классов необходимо краткое отступление. В С++ можно задать функцию, которая на самом деле не вызывается, а ее тело встраивается в программу в месте ее вызова. Она действует почти так же, как макроопределение с параметрами в С. Преимуществом встраиваемых 1и-Йпе) функций является то, что они не связаны с механизмом вызова функций и возврата ими своего значения. Это значит, что встраиваемые функции могут выполняться гораздо быстрее обычных. (Запомните, что выполнение машинных команд, которые генерируют вызов функции и возвращение функцией своего значения, занимает определенное время. Если функция имеет параметры, то ее вызов занимает еще большее время.) Недостатком встраиваемых функций является то, что если они слишком большие и вызываются слишком часто, объем ваших программ сильно возрастает.
Из-за этого применение встраиваемых функций обычно ограничивается короткими функциями. Для объявления встраиваемой функции просто впишите спецификатор 1ицпе перед определением функции. Например, в этой короткой программе показано, как объявить встраиваемую функцию: Пример встраиваемой функции ()ъпс1пг)е <1оеГпеазв> пв ' по пазлеярасе в1с(; зп1зпе гпС ечеп (згпв х) гевпгп ! (я%2 ); 1пс вазп () ( (езгеп(10) ) сопл « "10 является четньзм1п"; 11 (ечеп (11) ) сопл « 01 является четньмтп"; гегигп 0; В этом примере функция еуеп0, которая возвращает истину при четном аргументе, объявлена встраиваемой. Это означает, что строка 1Г (ечеп (10) ) соп( « "10 является четньы1п"; функционально идентична строке )г" 1! (1012) ) соп1 « "1О является четнымхп"; Этот пример указывает также на другую важную особенность использования встраиваемой функции: она должна быть задана до ее первого вызова.
Если Глава 2. Введение в классы это не так, компилятор нс будет знать, какой именно код предполагается встроить в программу с помощью встраиваемой функции. Поэтому функция ечепО была определена перед функцией шашО. В пользу использования встраиваемых функций вместо макроопределений с параметрами имеется два довода. Во-первых, они обеспечивают более стройный способ встраивания в программу коротких фрагментов кода. Например, при создании макроса с параметрами легко забыть, что для гарантии правильности встраивания в каждом случае часто требуются круглые внешние скобки. Встраиваемая функция исключает эту проблему. Во-вторых, компилятор гораздо лучше работает со встраиваемой функцией, чем с макрорасширением. Как правило, программисты С++ для многократных вызовов коротких функций вместо макросов с параметрами практически всегда используют встраиваемые функции.
Здесь важно понимать, что спецификатор шИпе для компилятора является запросом, а не командой. Если, по разным причинам, компилятор не в состоянии выполнить запрос, функция будет компилироваться, как обычная функция„а запрос шИве будет проигнорирован. В зависимости от типа вашего компилятора возможны некоторые ограничения на использование встраиваемых функций. Например, некоторые компиляторы не воспринимают функцию как встраиваемую, если функция является рекурсивной или если она содержит либо статическую (з1абс) переменную, либо любую инструкцию выполнения цикла, либо инструкцию ячйсИ, либо инструкцию яо$о.
Вам необходимо просмотреть руководство по вашему компилятору, чтобы точно определить ограничения на использование встраиваемых функций. Если какое-либо ограничение на использование встраиваемой функции нарушено, компилятор генерирует вместо нее обычную функцию. 1. Любая функция может стать встраиваемой, включая функции — члены классов. Например, функция гИчЫЫеО для ускорения ее выполнения сделана встраиваемой. (Функция возврашает истину, если ее первый аргумент без остатка может делиться на второй.) (( Демонстрация встраиваемой функции-члена втпс1ибе <Гсвг свата> цнппя патпеврасе з~с1; 74 с++ Самоучитель с1авв напр ( 1пс1> 3) рыЬ11с: загар(1пс а, 1пс Ь) 1пс Жч1в1Ые(); // встраивание происходит в этом определении заир:: затар(1п1 а, 1пг Ь) ( г =а; ) =Ь; /* Возврат 1, если 1 без остатка делится на .
тело этой функции- члена встраивается в программу */ 1п11пе 1пс зкпр::61чазъЬ1е() ( гесыгп ! (1%~) 1 1лг таьп() загар оЬ1 (10, 2), оЬ2 (10, 3); это истина ъг(оЬ1.с(1чтз1Ь1е()) соцс « "10 делится на 2~п"; это ложь 1г(оЬ2.с(Ы1з1Ь1е()) соцГ << "10 делится на Э~п"; гесыгп Оу 2. Допускается перегружать встраиваемую функцию. Например, эта программа перегружает ша() тремя способами. В каждом случае функция также объявляется встраиваемой.