Объявления и определения
Как было сказано ранее, объявление функции устанавливает ее имя, а также тип возвращаемого значения и список параметров. Определение функции, помимо этой информации, задает еще и тело – набор инструкций, заключенных в фигурные скобки. Функция должна быть объявлена перед вызовом. Например:
//
объявление функции calc()
//
определение находится в другом файле
void
calc(int);
int
main()
{
int
loc1 = get(); // ошибка:
get() не
объявлена
calc(loc1);
// правильно: calc() объявлена
}
//
...
С помощью ключевого слова extern, аналогичного объявлению функции: оно указывает, что объект определен в другом месте – в этом же исходном файле или в другом. Например:
extern int i;
Эта инструкция “обещает”, что в программе имеется определение, подобное
int i;
extern-объявление не выделяет места под объект. Оно может встретиться несколько раз в одном и том же исходном файле или в разных файлах одной программы. Однако обычно находится в общедоступном заголовочном файле, который включается в те модули, где необходимо использовать глобальный объект:
//
заголовочный
файл
extern
int obj1;
extern
int obj2;
//
исходный
файл
int
obj1 = 97;
int
obj2;
extern const double pi = 3.1416; // определение
const double pi; // ошибка: повторное определение pi
Ключевое слово extern может быть указано и при объявлении функции – для явного обозначения его подразумеваемого смысла: “определено в другом месте”. Например:
extern void putValues( int*, int );
Встраиваемые функции
В C++ можно задать функцию, которая на самом деле не вызывается, а ее тело встраивается в программу в месте ее вызова.
Спецификатор inline для функций помещается перед определением функции для того, чтобы код функции был подставлен компилятором непосредственно в место ее вызова для исключения накладных расходов по вызову функции (помещение параметров в стек, оформление возврата и прочее).
Inline void func(void) {тело функции}
При использовании inline-подстановки мы избавляемся от необходимости повторять многократно выкопировку одного и того же повторяющегося в программе фрагмента кода (как правило, небольшого по размеру) и сокращаем время выполнения программы за счет исключения вызовов подпрограмм и за счет увеличения размера занимаемой программой памяти.
Для объявления встраиваемой функции просто впишите спецификатор inline перед определением функции. Например, в этой короткой программе покзано, как объявить встраиваемую функцию:
//Пример встраиваемой функции #include<iostream>
using namespace std;
inline int even(int x) {
return !(x%2); }
int main()
{
if (even(10)) cout« "10 является четным W;
if (even(1l)) cout«; "11 является четными»;
return 0; }
В этом примере функция even(), которая возвращает истину при четном аргументе, объявлена встраиваемой. Это означает, что строка
if (even(10)) cout« "10 является четными";
функционально идентична строке
if (! (10%2)) cout « "10 является четным\п";
Этот пример указывает также на другую важную особенность использования встраиваемой функции: она должна быть задана до ее первого вызова. Если это не так, компилятор не будет знать, какой именно код предполагается встроить в программу с помощью встраиваемой функции. Поэтому функция even() была определена перед функцией main().
Примеры
Таким образом, если не указано иное, то имя, не являющееся локальным для функции или класса, в каждой части программы, компилируемой отдельно, должно относиться к одному и тому же типу, значению, функции или объекту. То есть, в программе может быть только один нелокальный тип, значение, функция или объект с этим именем. Рассмотрим, например, два файла:
// 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 было бы просто проигнорировано, поскольку описание с инициализацией всегда является определением. Объект в программе должен определяться только один раз. Описываться он может много раз, но типы должны точно согласовываться.
