Объявления и определения (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
    std::string str; // OK std::string is declared in <string> header
    C obj; // error! C not yet declared.
    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{/*...*/};
}

В строке 5 main объявлена функция. В строке 7 const 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. В строке 12 auto используется ключевое слово, которое указывает компилятору вывести тип k на основе значения, с которым он инициализируется. Компилятор в этом случае выбирает int тип.

Область видимости объявления

Имя, введенное в объявлении, допустимо в пределах области , в которой происходит объявление. В предыдущем примере переменные, объявленные внутри main функции, являются локальными переменными. Можно объявить другую переменную i , именованную за пределами Main, в глобальной области, и это будет отдельная сущность. Однако такое дублирование имен может привести к путанице и ошибкам программиста, и их следует избегать. В строке 21 класс C объявляется в области видимости пространства имен N . Использование пространств имен помогает избежать конфликтов имен. Большинство имен стандартных библиотек C++ объявляются в std пространстве имен. Дополнительные сведения о взаимодействии правил определения области с объявлениями см. в разделе Scope.

Определения

Некоторые сущности, включая функции, классы, перечисления и константные переменные, должны быть определены и объявлены. Определение предоставляет компилятору все сведения, необходимые для создания машинного кода, когда сущность используется позже в программе. В предыдущем примере строка 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 );

Определения типов и операторы using

В более старых версиях C++ typedef ключевое слово используется для объявления нового имени, которое является псевдонимом для другого имени. Например, типом std::string является другое имя для std::basic_string<char> . Должно быть очевидно, почему программисты используют имя typedef, а не фактическое имя. В современных C++ using ключевое слово предпочтительнее typedef , но идея одинакова: новое имя объявляется для сущности, которая уже объявлена и определена.

Члены статических классов

Поскольку члены статических данных класса являются дискретными переменными, общими для всех объектов класса, они должны быть определены и инициализированы вне определения класса. (Дополнительные сведения см. в разделе классы.)

объявления extern

Программа на C++ может содержать более одной единицы компиляции. Чтобы объявить сущность, определенную в отдельной единице компиляции, используйте extern ключевое слово. Сведения в объявлении достаточны для компилятора, но если определение сущности не удается найти на шаге компоновки, то компоновщик вызовет ошибку.

Содержимое раздела

Классы хранения в C
const
constexpr
extern
Инициализаторы
Псевдонимы и определения типов
using повторно
volatile
decltype
Атрибуты в C++

См. также

Основные понятия