Объявления и определения (C++)
Программа C++ состоит из различных сущностей, таких как переменные, функции, типы и пространства имен. Каждая из этих сущностей должна быть объявлена , прежде чем их можно будет использовать. Объявление указывает уникальное имя сущности, а также сведения о ее типе и других характеристиках. В C++ точка, в которой объявляется имя, является точкой, в которой оно становится видимым для компилятора. Вы не можете ссылаться на функцию или класс, объявленный позднее в блоке компиляции. Переменные следует объявлять как можно ближе к точке, в которой они используются.
В следующем примере показаны некоторые объявления:
#include <string>
int f(int i); // forward declaration
int main()
{
const double pi = 3.14; //OK
int i = f(2); //OK. f is forward-declared
C obj; // error! C not yet declared.
std::string str; // OK std::string is declared in <string> header
j = 0; // error! No type specified.
auto k = 0; // OK. type inferred as int by compiler.
}
int f(int i)
{
return i + 42;
}
namespace N {
class C{/*...*/};
}
В строке main
5 объявляется функция . В строке const
7 объявляется и инициализируется переменная с именемpi
. В строке 8 объявляется целое число i
и инициализируется значением, созданным функцией f
. Имя f
отображается компилятору из-за прямого объявления в строке 3.
В строке 9 объявляется переменная obj
типа C
. Однако это объявление вызывает ошибку, так как C
не объявляется до конца в программе и не объявляется вперед. Чтобы устранить эту ошибку, можно либо переместить все определениеC
ранее main
, либо добавить для него объявление вперед. Это поведение отличается от других языков, таких как C#. В этих языках функции и классы можно использовать до их объявления в исходном файле.
В строке 10 объявляется переменная str
типа std::string
. Имя std::string
отображается, так как оно появилось в string
файле заголовка, который объединяется с исходным файлом в строке 1. std
— это пространство имен, в котором string
объявлен класс .
В строке 11 возникает ошибка, так как имя j
не было объявлено. Объявление должно предоставлять тип, в отличие от других языков, таких как JavaScript. В строке auto
12 используется ключевое слово , которое указывает компилятору определить тип на основе значения, которым он инициализирован k
. Компилятор в этом случае выбирает int
тип .
Область видимости объявления
Имя, введенное объявлением, является допустимым в области, в которой происходит объявление. В предыдущем примере переменные, объявленные внутри main
функции, являются локальными переменными. Можно объявить другую переменную с именем i
за пределами main в глобальной области, и это будет отдельная сущность. Однако такое дублирование имен может привести к путанице и ошибкам программиста, и его следует избегать. В строке 21 класс C
объявляется в области пространства имен N
. Использование пространств имен помогает избежать конфликтов имен. Большинство имен стандартной библиотеки C++ объявлены в std
пространстве имен. Дополнительные сведения о взаимодействии правил области с объявлениями см. в разделе Область.
Определения
Некоторые сущности, включая функции, классы, перечисления и константные переменные, должны быть определены и объявлены. Определение предоставляет компилятору все сведения, необходимые для создания машинного кода при последующем использовании сущности в программе. В предыдущем примере строка 3 содержит объявление для функции f
, но определение функции предоставляется в строках 15–18. В строке 21 класс C
объявляется и определяется (хотя, как определено, класс ничего не делает). Константная переменная должна быть определена, другими словами, присвоено значение в той же инструкции, в которой она объявлена. Объявление встроенного типа, такого как, автоматически является определением, так как int
компилятор знает, сколько пространства для него нужно выделить.
В следующем примере показаны объявления, которые также являются определениями:
// Declare and define int variables i and j.
int i;
int j = 10;
// Declare enumeration suits.
enum suits { Spades = 1, Clubs, Hearts, Diamonds };
// Declare class CheckBox.
class CheckBox : public Control
{
public:
Boolean IsChecked();
virtual int ChangeState() = 0;
};
Ниже приведены некоторые объявления, которые не являются определениями:
extern int i;
char *strchr( const char *Str, const char Target );
Typedefs и операторы using
В более старых версиях C++ ключевое typedef
слово используется для объявления нового имени, которое является псевдонимом для другого имени. Например, тип std::string
— это другое имя для std::basic_string<char>
. Должно быть очевидно, почему программисты используют имя определения типа, а не фактическое имя. В современном C++ ключевое using
слово предпочтительнее typedef
, но идея та же: новое имя объявляется для сущности, которая уже объявлена и определена.
Статические члены класса
Статические члены данных класса — это дискретные переменные, которые совместно используются всеми объектами класса . Так как они совместно используются, они должны быть определены и инициализированы вне определения класса. Дополнительные сведения см. в разделе Классы.
объявления extern
Программа C++ может содержать несколько единиц компиляции. Чтобы объявить сущность, определенную в отдельном блоке компиляции, используйте ключевое extern
слово . Информации в объявлении достаточно для компилятора. Однако если определение сущности не удается найти на шаге связывания, компоновщик вызовет ошибку.
В этом разделе
Классы хранения в C
const
constexpr
extern
Инициализаторы
Псевдонимы и определения типов
using
Декларации
volatile
decltype
Атрибуты в C++