GCC - The Complete Reference (537669), страница 25
Текст из файла (страница 25)
срр и хранящийся в библиотеке 11Ьвау.а. Как 11Ьгагувау. ваутМв (), так и 11Ьгагувау. ваувсгйпд() являются вызовами методов объекта библиотеки. Также и вауЬе11о() является вызовом функции из объектного файла вауЬе11о. о, который также находится в этой библиотеке. При запуске программы происходит вывод следующих строк; Ье11о ггоа а веае1с 11Ьгагу Ьотнту ггоа а всавъс 11Ьгагу ььЬгагу 1пвеапсе ог вау Ьоса1 1пвгапсе ог Вау Создание разделяемой библиотеки Разделяемая библиотека (зйаге() ВЬгагу) также содержит набор объектных файлов.
Только ее объектные модули должны использовать относительную адресацию, чтобы их код мог быть динамически загружен в любую область памяти и запущен оттуда без его избыточного перемещения. Это позволяет загружать исполняемый код из разделяемой библиотеки во время выполнения программы, вместо его статической компоновки в исполняемый файл. Приведенный далее заголовочный файл с именем ачегаде. Ь определяет класс, который должен быть сохранен в разделяемой библиотеке: /* ачегаде.Ь */ с1авв Ачегаде ( рг1чаее: 1пе сопев/ ДопЫе Еоеа1; риЫ)с: Ачегаде(чо16) соипе = 01 Соса1 = О.О; чо1о ьпвегсча1ие(цобе ча1ие] г 1пе деесоопе(чо1с)/ с(оиые дестоеа1(чо1а)г етоиЫе десачЕГада(чс16); )' Исходный файл ачегаде. срр, который также должен быть скомпилирован и сохранен в разделяемой библиотеке, содержит код функций, определенных в классе Ачегаде: /* ачегаде.срр */ Взпс1пе)е "ачегаде.Ь" Глава б.
Компиляция программ на языке С++ 1 1 5 чс)й Ачегадет:1пвегсча1ие(йоиЬ1е ча1ие) < осипе++; Ссга1 += ча1ие; ) 1пг Ачегадеь:двсосипс() ( гвеигп(осипе); ) йоивье АчЕГада1: даетсса1 ( ) ( гегигп(ссга1)ю ) йаиьте Ачегаде::дегвчегаде() ( гегигп(соса1 / (йоиЬ1е)соипс)г ) Исходные файлы компилируются в объектные, которые затем используются для построения разделяемой библиотеки. Это происходит нри вынолнении следующих двух команд: д д++ -с -1рьс ачегаде.срр д дсс -вЬагей ачегаде.о -о ачегаде.во Первая команда иснользует опцию -с, поэтому компилятор вырабатывает объектный файл ачегаде. о и не предпринимает полыткн его компоновки в иснолниинй машинный код.
Онция -арго ("Р)с" — сокращение от англ. "Роз)(юп! ндереядеп( Соде" — "независимый от ноложения код*') указывает компилятору вырабатывать пригодный для разделяемой библиотеки код. Т.е. такой код, в котором внутренняя щ(ресация вычисляется относительно начального адреса загрузки модуля в память, Вторая команда использует опцию -вЬагей, что ври водит к созданию разделяемой библиотеки с именем ачегаде. ао (указанным опцией -о). Для второй команды можно применить как команду д++, так и дсс. Создание разделяемой библиотеки из объектных файлов при компиляци С++ не имеет никаких особенных отличий от абщей процедуры.
Для сборки библиотеки из нескольких файлов достаточно их просто перечислить в командной строке. Две нредыдущие команды можно объединить в одну. По ней исходные файлы компилируются в объектные, из которых затем создается разделяемая библиотека: д д++ -гр1с -вЬагей ачегаде.срр -о ачегаде.во Следующая нрограмма использует определение класса, находящееся в разделяемой библиотеке, лля создания экземпляра объекта, который применяется для помещения в него 4-х значений и расчета их обшей суммы: /* вьсначегаде.срр */ «(пс1ийе <1овсгеаш> а)пс1ийе "ачегеде.Ь" 1пс паап(1пе агдс,сЬаг *агдч()) ( Ачегаде ачд( 1 16 Часть!!. Использование Сборного Компилятора ачд.
1пвегсча1ив (30. 2) г ачд.1пвегеуа1ив(88.8)г ачд.1пвегетга1ие(3.002)г ачд.1пвегечв1ие(11.0)г вебггсоиа « "Ачегаде=" « ачд.деЕАчекаде() « бтп"г гееигп(О)) Далее приведена команда лля компиляции и компоновки программы с разделяемой библиотекой. По этой команде вырабатывается файл вЬоыачегаде с исполнимым машинным кодом: 8 д++ вцсыачегаде.срр ачегаде.во -о вьоывчегаде Для запуска программы библиотека ачегаде. во должна быть установлена в каталоге, разрешимом для поиска разделяемой библиотеки во время выполнения программы.
Подробнее об этом — в главе 12. Расширения языка С++ Атрибуты (А11пЬШеи) В главе 4 приведен список атрибутов, используемых в программах на языке С. Эти атрибуты применимы также и для программ на языке С++. Кроме них имеются особые атрибуты, используемые только в С++. Атрибут применяется указанием ключевого слова ассг1Ьисе со следующим за ним заключенным в скобки именем атрибута. В таблице 5.2 содержится описание только особых специально разработанных для языка С++ атрибутов, поддерживаемых в ССС.
Таблица 5.2. Список особых атриб ов, используемых а программах иа языке С++ Стандарт С++ определяет, что инициализация объектов происходит в том порядке, в котором они расположены в компилируемом модуле(цпй), В стандарте нет особой спецификация о последовательности нх инициализации между модулями. Атрибут 1п1к рг1иг1гу предоставляет возможность указания, в какой последовательности должна происходить инициализация сбьектсв в пределах выделяемой области памяти. Объектам прн нх объявлении назначаются приоритеты в соответствия с указанными числами. Приоритет тем выше, чем меньшее число указано в параметре атрибута.
В следующем примере трн объекта будут нннцнаянзнрсваны в таком порядке — сначала в, затем с н только потом А независимо ст того, в каком модуле снн находятся; 1п1Ь рк1ог1ку Этот раздел разъясняет применяемые в Сг)ч(3 расширения стандартных правил языка С++. Компилятор С++ весьма сложен, и документ, определяющий его стандарт, имеет довольно большой объем.
Здесь, конечно, описаны не все расширения языка и не все расхождения со стандартом. Тут также опущены многие расширения, унаследованные от компилятора Сг)ч() С и применяемые при компиляции в ССС программ на языке С++ (они перечислены в главе 4). Глава б. Компиляция программ на языке С++ 1 17 вросзавв а акта(веке ((1л1к ркдск(ку(вес) ) ) г вросзава в аккк1ьаке ((1п(к ркяокдку(ззо) ) ); вростаае с аккк1ьоке ((1п(к ркяок(ку(еоо) ) ) г Числа, указанные в параметре атрибута, не имеют никакого особого значения, кроме их величины относительно друг друга. Атрибут указывает, что класс должен быть определен как интерфейс даик Этот атрибут применим только к классам, имеющим внутри себя определение блока ехкекл "сета'ч Вызов методов класса, определенного таким способом, использует интерфейс ССЗ таблицы виртуальных функций С++.
рата (ваекеасе Включаемые заголовочные файлы (Неадег 6!ез) Все системные заголовочные файлы включаются по умолчанию, если они заклю- ЧЕНЫ В бЛОК ЕХСЕГП нСн (... ) . ЭтО ВЫЗЫВаЕт ПрОбЛЕМЫ, КОГда ЗаГОЛОВОЧНЫй файЛ содержит код на языке С++. Однако эти проблемы легко разрешить, если применить директивой препроцессора следующую прагму: Мргадша ср1овр1ив При применении такой прагма-директивы в заголовочном файле дальнейший код компилируется так, как если бы он был заключен в блок ехеегп нс++" (... ) . ПряМОЕ ИСПОЛЬЗОВаинс Этсй ПраГМЫ НЕПОСрЕдСтВЕННО В бЛОКЕ ЕХЕЕГП аС" (...
) является ошибкой. Имена функций г'* вЬсияопспаше.срр */ й(пс1о((е <1овсгеаш> с1авв Хух ( ри)г11с г уо1кт мешая)тои(1пе 1,ктоиьте 6) ( всгткксоис « " РОМСТХОМ хп «РОМСТХОМ « "хп" Г вепк:соое « " Рввтту Ромсттом (п « РВЕТТУ РЦМСТ1ОМ « "хп" Г вебк;сопс « " кепс хп «яопс «ахп") ) )) 1пс ша1п(1пс агяс,сЪаг *агду(]) ( идентификатор Рцмсттом содержит имя текущей функции, как в языке с, тяк и в С++. В языке С++ РННТТТ РЦМСт1ОМ также содержит имя функции, но только в форме, предоставляющей больше информации. В примере показано применение этих идентификаторов, а также идентификатора бппс, определенного стандартом языка С: 1 18 часть н.
использование сборного компилятора Хув хувг хув.наеееиое(5,5.0)) гевого(0)( ) При выполнении эта программа выводит такие строки: РзэноттОМ Матея)зон Риетту Рпмсттом чото Хув: гназвевиои (Зле, г)оа)зте) хаос Маеевцои Идентификаторы упмст1ОМ и бцпс определены как строки, содержащие только само имя текущей функции.
идентификатор Рннтту Рпмстт(зм содержит полное имя текущей функции, включая тип возвращаемого результата, имя класса и список типов аргументов. Объявление класса и код его реализации (1п1ег1асе и 1вр!еаеп1абоп) Объявление класса и код его реализации можно объединить в одно целое. Это означает, что нет необходимости в отдельном объявлении прототипа класса, потому что код, полностью реализующий класс, может применяться в его интерфейсном определении.
Это достигается выбором директивы йргадша 1оеегбасе для указания определения класса только в качестве его интерфейса (т.е. объявления прототипа) или ()рга(рва 1вр1емепсасйоп двя указания ОСС компилировать определения функций и данных класса в объектный код. Это очень удобная )рича" и ее использует немало программистов, но в скором времени планируется ее замена. Похоже, что в будущей версии 6СС от этой пары прагм откажутся, и для достижения того же результата будет применяться другой механизм. Для использования этой пары прагм можно применять следующую последовательность действий: 1.
Создайте заголовочный файл, содержащий полную реализацию класса. Например, файл для класса махно1г)ег может быть назван а(ах)то1г)ег.)з, 2. В начале заголовочного файла и после определения класса поставьте строку: «ргаяаа 1пеегсасе 3. В любом исходном файле, ссылающемся на класс махио1г)ег, включайте заголовочный файл обычным способом. 4. В одном из исходных файлов (обычно это делается в файле, содержащем главную процедуру) перед директивой ййпс1цое вставьте следующую прагма-директи ву: Глава 6. компиляция программ на языке с++ 1 19 Мргадша 1ш1ешепсае1оп "шахпо1ктег.Ь" Ипс1пйе "шахпа1ктег.Ь" Файлы, включающие заголовочный файл ()чеадег Ие) обычным способом, будут подключать только интерфейсное определение класса, в то время как один файл с директивой Мргадша фш1ешепеасфоп подключит полный исходный код класса, тот код, который будет скомпилирован в объектный формат.