Основы программирования

Наследство от языка Си - Компоновка
Индекс материала
Наследство от языка Си
Область Видимости
Объекты и Адреса (Lvalue)
Имена
Типы
Неявное Преобразование Типа
Тип void
Указатели
Вектора
Структуры
Эквивалентность типов
Регистры
Константы
Символьные Константы
Строки
Const
Перечисления
Экономия Пространства
Упражнения
Выражения и Операторы
Программа синтаксического разбора
Функция ввода
Таблица имен
Обработка ошибок
Драйвер
Параметры командной строки
Краткая сводка операций
Порядок вычисления
Побитовые логические операции
Преобразование типа
Свободная память
Сводка операторов
Проверки
Goto
Комментарии и Выравнивание
Упражнения
Функции и Файлы
Компоновка
Заголовочные Файлы
Один Заголовочный Файл
Множественные Заголовочные Файлы
Сокрытие Данных
Файлы как Модули
Как Создать Библиотеку
Функции
ередача Параметров
Возврат Значения
Векторные Параметры
Параметры по Умолчанию
Перегрузка Имен Функций
Незаданное Число Параметров
Все страницы


4.2 Компоновка

Если не указано иное, то имя, не являющееся локальным для функции или класса, в каждой части программы, компилирумой отдельно, должно относиться к одному и тому же типу, знчению, функции или объекту. То есть, в программе может быть только один нелокальный тип, значение, функция или объект с этим именем. Рассмотрим, например, два файла:

// file1.c: int a = 1; int f() (* /* что-то делает */ *)

// file2.c: extern int a; int f(); void g() (* a = f(); *)

a и f(), используемые g() в файле file2.c,– те же, что определены в файле file1.c. Ключевое слово extern (внешнее) указывает, что описание a в file2.c является (только) описнием, а не определением. Если бы a инициализировалось, extern было бы просто проигнорировано, поскольку описание с иницилизацией всегда является определением. Объект в программе должен определяться только один раз. Описываться он может много раз, но типы должны точно согласовываться. Например:

// file1.c: int a = 1; int b = 1; extern int c;

// file2.c: int a; extern double b; extern int c;

Здесь три ошибки: a определено дважды (int a; является определением, которое означает int a=0;), b описано дважды с разными типами, а c описано дважды, но не определено. Эти вды ошибок не могут быть обнаружены компилятором, который за один раз видит только один файл. Компоновщик, однако, их онаруживает.

Следующая программа не является С++ программой (хотя C программой является):

// file1.c: int a; int f() (* return a; *)

// file2.c: int a; int g() (* return f(); *)

Во-первых, file2.c не С++, потому что f() не была описана, и поэтому компилятор будет недоволен. Во-вторых, (когда file2.c фиксирован) программа не будет скомпонована, посколку a определено дважды.

Имя можно сделать локальным в файле, описав его static. Например:

// file1.c: static int a = 6; static int f() (* /* ... */ *)

// file2.c: static int a = 7; static int f() (* /* ... */ *)

Поскольку каждое a и f описано как static, получающаяся в результате программа является правильной. В каждом файле своя a и своя f().

Когда переменные и функции явно описаны как static, часть программы легче понять (вам не надо никуда больше залядывать). Использование static для функций может, помимо этого, выгодно влиять на расходы по вызову функции, поскольку дает оптимизирующему компилятору более простую работу.

Рассмотрим два файла:

// file1.c: const int a = 6; inline int f() (* /* ... */ *) struct s (* int a,b; *)

// file1.c: const int a = 7; inline int f() (* /* ... */ *) struct s (* int a,b; *)

Раз правило «ровно одно определение» применяется к контантам, inline-функциям и определениям функций так же, как оно применяется к функциям и переменным, то file1.c и file2.c не могут быть частями одной С++ программы. Но если это так, то как же два файла могут использовать одни и те же типы и константы? Коротко, ответ таков: типы, константы и т.п. могут определяться столько раз, сколько нужно, при условии, что они определяются одинаково. Полный ответ несколько более сложен (это объясняется в следующем разделе).




 
Кровля из гибкой черепицы - гибкая черепица цена. Кровля по лучшим ценам! Скидки.