Объявление (declaration) сообщает компилятору, что такое имя существует. Определение (definition) действительно создаёт объект.
Зачем нужно
В C++ имя должно быть объявлено до использования. Этот код не компилируется,
хотя x — настоящая глобальная переменная:
int main() {
int y = 2;
std::cout << x + 3 * y << '\n'; // ошибка
return 0;
}
int x = 1;В момент чтения строки с std::cout компилятор ещё не знает, что такое x.
Как работает
Имя можно заранее объявить, а переменную определить позже. Для этого есть
ключевое слово extern:
int main() {
int y = 2;
extern int x; // объявление без определения
std::cout << x + 3 * y << '\n';
return 0;
}
int x = 1; // определение xextern int x; объекта не создаёт — только обещает компилятору, что
переменная x типа int где-то определена. Создаёт её строка int x = 1;.
Обычное int x; внутри функции — это объявление и определение сразу: объект
уже существует, хотя начального значения у него нет. Об этом —
Инициализация переменных.
Тонкости
- В учебном коде проще писать глобальные переменные до функций, и
externне понадобится. - Различие объявления и определения дальше будет встречаться постоянно: в функциях, заголовочных файлах и раздельной компиляции — см. Подключение заголовков и Компиляция и сборка.
- Объявление делает имя доступным, но только с места объявления и в пределах его области видимости.
Частые ошибки
- Определить глобальную переменную ниже функции, которая её использует, и
удивляться
was not declared in this scope. - Считать, что объявление всегда создаёт объект:
extern int x;ничего не создаёт.
Углубление — L05
Функции подчиняются тому же правилу: имя должно быть объявлено до вызова. Объявление функции — заголовок без тела, с точкой с запятой; определение — с телом:
int Min(int x, int y); // объявление
int main() {
return Min(10, 20); // OK: Min уже объявлена
}
int Min(int x, int y) { // определение
return x < y ? x : y;
}Без первой строки вызов — Min is not declared here. В объявлении функции
имена параметров можно опустить: int Min(int, int);. Ключевое слово
extern для функций не нужно — объявление без тела и так ничего не создаёт.
Правило одного определения (One Definition Rule, ODR). Согласованные
объявления можно повторять сколько угодно; определение с телом — одно, даже
если второе тело совпадает с первым (redefinition). Если функцию объявили и
вызвали, но не определили нигде, компилятор пропустит программу, а упадёт
компоновка. Подробнее — Функция.
Не из лекции
Про ненужность
externу функций лекция не говорит — это пояснение к разнице с примером из L02.