Спецификатор typedef
typedef
- создаёт псевдоним, который можно использовать где угодно вместо (возможно, сложного) имени типа.
Содержание |
[править] Объяснение
Спецификатор typedef при использовании в объявлении, указывает, что объявление является объявлением typedef, а не объявлением переменной или функции. Как правило, спецификатор typedef появляется в начале объявления, хотя ему разрешено появляться после спецификаторов типа или между двумя спецификаторами типа.
Объявление typedef может объявлять один или несколько идентификаторов в одной строке (например, int и указатель на int), оно может объявлять типы массивов и функций, указатели и ссылки, классовые типы и т.д. Каждый идентификатор, представленный в этом объявлении, становится именем typedef, которое является синонимом типа объекта или функции, которыми он станет, если ключевое слово typedef будет удалено.
Спецификатор typedef нельзя комбинировать ни с каким другим спецификатором, кроме спецификаторов-типа.
Имена typedef являются псевдонимами существующих типов, а не объявлениями новых типов. Typedef нельзя использовать для изменения значения существующего имени типа (включая имя typedef). После объявления имя typedef может быть повторно объявлено только для повторной ссылки на тот же тип. Имена typedef действуют только в той области видимости, где они видны: разные объявления функций или классов могут определять типы с одинаковыми именами и разными значениями.
Спецификатор typedef
не может появиться ни в объявлении параметра функции, ни в последовательности-спецификаторов-объявления определения функции:
void f1(typedef int param); // не верно typedef int f2() {} // не верно
Спецификатор typedef
не может появиться в объявлении, не содержащем декларатора:
typedef struct X {}; // не верно
[править] Имя typedef для целей связывания
Формально, если объявление typedef определяет безымянный класс или перечисление, первое имя typedef, объявленное объявлением как классовый тип или тип перечисления, используется для обозначения классового типа или типа перечисления только для целей связывания. Например, в typedef struct { /* ... */ } S;, S является именем typedef для целей связывания. Определённый таким образом тип класса или перечисления имеет внешнее связывание (если только он не находится в безымянном пространстве имён).
Безымянный класс, определённый таким образом, должен содержать только C-совместимые конструкции. В частности, он не должен
и все классы-элементы также должны соответствовать этим требованиям (рекурсивно). |
(начиная с C++20) |
[править] Ключевые слова
[править] Примечание
Псевдонимы типов обеспечивают ту же функциональность, что и определения типов, но с другим синтаксисом, а также применимы к именам шаблонов.
[править] Пример
// простой typedef typedef unsigned long ulong; // следующие два объекта имеют одинаковый тип unsigned long l1; ulong l2; // более сложный typedef typedef int int_t, *intp_t, (&fp)(int, ulong), arr_t[10]; // следующие два объекта имеют одинаковый тип int a1[10]; arr_t a2; // будьте осторожны: следующие два объекта не имеют один и тот же тип const intp_t p1 = 0; // int *const p1 = 0 const int *p2; // общая идиома C, чтобы не писать "struct S" typedef struct {int a; int b;} S, *pS; // следующие два объекта имеют одинаковый тип pS ps1; S* ps2; // ошибка: спецификатор-класса-хранения не может появиться в объявлении typedef // typedef static unsigned int uint; // typedef можно использовать в любом месте последовательности-спецификаторов-объявления. long unsigned typedef int long ullong; // более просто пишется "typedef unsigned long long int ullong;" // std::add_const, как и многие другие метафункции, использует typedef с элементами template<class T> struct add_const { typedef const T type; }; typedef struct Node { struct listNode* next; // объявляет новый (неполный) тип структуры с именем listNode } listNode; // ошибка: конфликтует с ранее объявленным именем структуры // ошибка C++20: "структура с именем typedef для связывания" имеет функции-элементы typedef struct { void f() {} } C_Incompatible;
[править] Отчёты о дефектах
Следующие изменения поведения были применены с обратной силой к ранее опубликованным стандартам C++:
Номер | Применён | Поведение в стандарте | Корректное поведен��е |
---|---|---|---|
CWG 576 | C++98 | нельзя использовать во всём определении функции | разрешено в теле функции |
CWG 2071 | C++98 | typedef может появиться в объявлении, не содержащем декларатора
|
теперь запрещено |
[править] Смотрите также
Документация C по Объявление typedef
|