Программирование >>  Оптимизация возвращаемого значения 

1 ... 84 85 86 [ 87 ] 88 89 90 ... 96


в с образом, но как же именно, не слишком понятно. Тем не менее, это всегда значит, что корректировка имени функции должна подавляться.)

Например, если вам пришлось написать функцию на ассемблере, вы также можете объявить ее при помоши директивы extern С :

Эта функция написна на ассемблере - не корректировать ее имя.

extern С void twiddleBits (unsigned char bits) ;

Можно даже объявлять с extern С функции С++. Это может быть полезно, если вы пишете библиотеку на С++ и хотите, чтобы она была доступна пользователям других языков программирования. Благодаря подавлению корректировки имен для функций С++ программисты могут использовать естественные и наглядные имена вместо тех, которые бы автоматически создал компилятор:

Следующая функция С++ предназначена для использования в других языках, поэтому ее имя не должно корректироваться, extern С void simulate(int iterations);

Для многих функций корректировка имени не должна выполняться, и было бы тяжело писать extern С перед каждой из них. К счастью, это не нужно. Можно применить директиву extern С ко всему набору функций, просто заключив его в фигурные скобки:

extern С {

Запретить корректировку имени для всех этих функций, int у2) ;

void drawLine (int х1, intyl, int x2 , void twiddleBits (unsigned char bits) ; void simulate(int iterations);

Применение директивы extern С упрощает поддержку заголовочных файлов, которые должны использоваться и в С, и в С++. При компиляции в С++ нужно включать директиву extern С , а при компиляции в С нет. Воспользовавшись

тем, что символ препроцессора cplusplus определен только при компиляции

в С++, можно придать многоязычным заголовочным файлам следующую структуру:

#ifdef cplusplus

extern С { #endif int у2);

void drawLine(int xl, int yl, int x2, void twiddleBits (unsigned char bits) ; void simulate(int iterations);

#ifdef cplusplus

#endif



Между прочим, не существует стандартного алгоритма коррекции имен. Различные компиляторы могут выполнять коррекцию имен по-разному, и они так и делают. Это неплохо. Если бы все компиляторы выполняли коррекцию имени одинаковым образом, сложилось бы впечатление, будто они создают совместимый код. При существующем положении вещей, если попытаться смешать объектный код, полученный при помощи несовместимых компиляторов С++, весьма вероятно, что во время компоновки у вас на экране появится сообщение об ошибке, так как скорректированные имена функций не будут совпадать. Это будет означать, что, вероятно, кроме рассмотренной, есть еще и другие проблемы совместимости, и лучше обнаружить их как можно раньше.

Инициализация статических обтектов

После того как вы овладели коррекцией имен, вам нужно справиться с тем, что в С++ большая часть кода может выполняться как до, так и после вызова функции main. В частности, конструкторы статических объектов, принадлежащих классам, и объектов в глобальном и других пространствах имен обычно вызываются до выполнения данной функции. Такой процесс называется инициализацией статических объектов (static initialization). Это прямо противоположно нашему обычному взгляду на программы С и С++, когда функция main рассматривается как точка входа в программу. Аналогично, деструкторы объектов, создаваемые в процессе инициализации статических объектов, должны вызываться во время уничтожения статических объектов (static destruction); этот процесс обычно происходит после того, как выполнение функции main уже завершено.

Для разрешения этой дилеммы, когда с одной стороны предполагается, что функция main должна вызываться первой, а с другой стороны - что до выполнения функции main должны создаваться объекты, многие компиляторы вставляют в начало функции main специально сгенерированную компилятором функцию, которая и заботится об инициализации статических объектов. Аналогично, компиляторы часто вставляют в конце функции main вызов другой специальной функции, которая заботится об уничтожении статических объектов. Код, автоматически созданный для функции main, часто выглядит примерно так:

int main(int argc, char *argv[]) {

performStaticInitialization{); Создается

компилятором.

операторы, входящие в функцию main;

performStaticDestruction{); Создается

компилятором.

Не воспринимайте это буквально. Функции performstaticlnitialization и performStaticDestruction обычно имеют более загадочные имена, а также могут быть встроенными, и в этом случае вы не увидите их в объектном файле. Важно следующее: при выборе компилятором С++ такого подхода к инициализации и уничтожению статических объектов они будут создаваться и уничтожаться,



только если функция main написана на С++. Поскольку это общепринятый подход к инициализации и уничтожению статических объектов, то если какая-то часть системы написана на С++, вы должны постараться написать функцию main также на С++.

Иногда кажется более осмысленным написать функцию main на С - скажем, когда большая часть программы написана на С, а на С++ только вспомогательная библиотека. Тем не менее, не исключено, что библиотека С++ содержит статические объекты (если не сейчас, то возможно в будущем - см. правило 32), поэтому все же лучше написать функцию main на С++. Это не означает, что вам нужно переписывать код С. Просто переименуйте написанную на С функцию main в realMain, а затем вызовите ее из функции main, написанной на С++.

extern С Напишите эту

int realMain (int argc, char *argv[] ) ; функцию на С.

int main (int argc, char *argv[] ) A эту на С++.

return realMain(argc, argv);

При этом неплохо поместить перед функцией main комментарий, объясняющий, что происходит.

Если вы не можете написать функцию main на С++, наверняка столкнетесь с проблемой, поскольку нет другого переносимого способа убедиться в том, что будут вызываться конструкторы и деструкторы статических объектов. Это не означает, что все потеряно, но вам придется больше потрудиться. Производители компиляторов хорошо знакомы с данной проблемой, поэтому почти все из них предоставляют какой-либо межъязыковый механизм для запуска процесса инициализации и уничтожения статических объектов. За соответствующей информацией обратитесь к документации компилятора или свяжитесь с производителем.

Динамическое выделение памяти

Вопрос инициализации и уничтожения статических объектов подводит нас к проблеме динамического выделения памяти. Здесь действует общее простое правило; части программы, написанные на С++, используют операторы new и delete (см. правило 8), а части, написанные на С, используют функции malloc (и ее варианты) и free. Пока память, полученная при помощи new, освобождается посредством delete, а память, полученная при помощи malloc, освобождается функцией free, все будет в порядке. Однако вызов функции free для указателя, полученного при помощи new, приведет к неопределенному поведению, так же как и удаление оператором delete указателя, полученного при помощи функции malloc. Следовательно, нужно строго разделять использование new и delete от malloc и free.

Иногда это легче сказать, чем выполнить. Рассмотрим скромную (но удобную) функцию strdup, которая, не являясь стандартной ни в С, ни в С++, применяется очень широко:



1 ... 84 85 86 [ 87 ] 88 89 90 ... 96

© 2006 - 2024 pmbk.ru. Генерация страницы: 0.001
При копировании материалов приветствуются ссылки.
Яндекс.Метрика