Объявления классов Token
и Token_stream
находятся в заголовке token.h
. Их определения находятся в файле token.cpp
. В языке C++ расширение .h
относится к заголовочным файлам, а расширение .cpp
чаще всего используется для исходных файлов. На самом деле в языке С++ расширение файла не имеет значения, но некоторые компиляторы и большинство интегрированных сред разработки программ настаивают на использовании определенных соглашений относительно расширений файлов.
В принципе директива #include "file.h"
просто копирует объявления из файла file.h
в ваш файл в точку, отмеченную директивой #include
. Например, мы можем написать заголовочный файл f.h
.
// f.h
int f(int);
А затем можем включить его в файл user.cpp
.
// user.cpp
#include "f.h"
int g(int i)
{
return f(i);
}
При компиляции файла user.cpp
компилятор выполнит подстановку заголовочного файла и скомпилирует следующий текст:
int f(int);
int g(int i)
{
return f(i);
}
Поскольку директива #include
выполняется компилятором в самом начале, выполняющая ее часть компилятора называется
Token_stream::putback()
сделал ошибки.
Token Token_stream::putback(Token t)
{
buffer.push_back(t);
return t;
}
Этот фрагмент выглядит вполне невинно. К счастью, компилятор перехватывает ошибки, потому что он видит (благодаря директиве #include
) объявление функции Token_stream::putback()
. Сравнивая это объявление с соответствующим определением, компилятор выясняет, что функция putback()
не должна возвращать объект класса Token
, а переменная buffer
имеет тип Token
, а не vector
, так что мы не можем использовать функцию push_back()
. Такие ошибки возникают, когда мы работаем над улучшением кода и вносим изменения, забывая о необходимости согласовывать их с остальной частью программы.
Рассмотрим следующие ошибки:
Token t = ts.gett(); // ошибка: нет члена gett
// ...
ts.putback(); // ошибка: отсутствует аргумент
Компилятор немедленно выдаст ошибку; заголовок token.h
предоставляет ему всю информацию, необходимую для проверки.
Заголовочный файл std_lib_facilities.h
содержит объявления стандартных библиотечных средств, таких как cout
, vector
и sqrt()
, а также множества простых вспомогательных функций, таких как error()
, не являющихся частью стандартной библиотеки. В разделе 12.8 мы продемонстрируем непосредственное использование заголовочных файлов стандартной библиотеки.
Заголовки обычно включаются во многие исходные файлы. Это значит, что заголовок должен содержать лишь объявления, которые можно дублировать в нескольких файлах (например, объявления функций, классов и числовых констант).
8.4. Область видимости
void f()
{
g(); // ошибка: g() не принадлежит (пока) области видимости
}
void g()
{
f(); // OK: функция f() находится в области видимости
}
void h()
{
int x = y; // ошибка: переменная y не принадлежит (пока)
// области видимости
int y = x; // OK: переменная x находится в области видимости
g(); // OK: функция g() находится в области видимости
}
Имена, принадлежащие области видимости, видны из вложенных в нее других областей видимости. Например, вызов функции f()
находится в области видимости функции g()
, которая является вложенной в глобальную область видимости. Глобальная область видимости не вкладываются ни в какую другую. Правило, утверждающее, что имя должно быть объявлено до того, как будет использовано, по-прежнему действует, поэтому функция f()
не может вызывать функцию g()
.
Существует несколько разновидностей областей видимости, которые можно использовать для управления используемыми именами.