Перейти к содержимому
Теория · Функции · урок 1 из 11

Объявление и определение

Компилятор (compiler) читает файл сверху вниз. Когда он встречает вызов функции, ему уже нужно знать её имя, типы параметров (parameters) и тип результата. Поэтому функцию, определённую ниже main, вызвать из main не получится:

C++
#include <iostream>

int main() {
    std::cout << twice(21) << '\n';  // ✗
}

int twice(int x) {
    return x * 2;
}
TEXT
error: use of undeclared identifier 'twice'

Можно перенести twice выше main, и ошибка исчезнет. Но если функция определена в другом файле, переносить нечего — о ней нужно сообщить компилятору иначе.

Объявление

Объявление (declaration) сообщает компилятору имя функции, типы её параметров и тип результата. Тела у объявления нет — вместо него стоит точка с запятой. Такое объявление ещё называют прототипом.

C++
int twice(int x);

Имена параметров в объявлении можно не писать: int twice(int); значит то же самое. Компилятору нужны только типы, а имя x подсказывает читателю, что передаётся в функцию.

Определение (definition) — это объявление вместе с телом в фигурных скобках, поэтому функцию, определённую выше main, отдельно объявлять не нужно. Объявить функцию можно несколько раз, а определить — только один.

Вызов до определения

Объявление выше main решает задачу: вызов компилируется, а тело может стоять в конце файла.

C++
#include <iostream>

int twice(int x);

int main() {
    std::cout << twice(21) << '\n';  // 42
}

int twice(int x) {
    return x * 2;
}

Чтобы проверить вызов twice(21), компилятору хватает объявления: функция принимает int и возвращает int. Если тело лежит в другом .cpp-файле, вызов с ним свяжет компоновщик (linker). На этом основаны заголовочные файлы (header files): в них пишут объявления, а определения — в .cpp-файлах. Так устроен и #include <iostream>: он вставляет в файл объявления из стандартной библиотеки.

Частая ошибка

Функцию объявили, а определить забыли. Компилятор ошибки не видит, и сборка (build) останавливается на следующем шаге:

C++
int twice(int x);

int main() {
    return twice(21);  // ✗
}
TEXT
undefined reference to `twice(int)'

Это сообщение компоновщика, а не компилятора: объявления хватило, чтобы проверить вызов, но тела twice нет ни в одном файле программы. В задачах курса то же сообщение выглядит иначе: undefined symbol: twice(int).

Та же ошибка появится, если определение не совпадёт с объявлением по типам параметров. int twice(long x) — уже другая функция, и объявленная twice(int) снова останется без тела.