Псевдонимы и определения типов (C++)
Объявление псевдонима можно использовать для объявления имени, используемого в качестве синонима для ранее объявленного типа. (Этот механизм также называется неформальным псевдонимом типа. Этот механизм также можно использовать для создания шаблона псевдонима, который может быть полезен для пользовательских распределителей.
Синтаксис
using identifier = type;
Замечания
идентификатор
Имя псевдонима.
type
Идентификатор типа, для который вы создаете псевдоним.
Псевдоним не вводит новый тип и не может изменить значение существующего имени типа.
Простейшая форма псевдонима эквивалентна механизму typedef C++03:
// C++11 using counter = long; // C++03 equivalent: // typedef long counter;
Обе эти формы позволяют создавать переменные типа counter . Псевдоним типа для std::ios_base::fmtflags , приведенный в следующем примере, может быть более полезен.
// C++11 using fmtfl = std::ios_base::fmtflags; // C++03 equivalent: // typedef std::ios_base::fmtflags fmtfl; fmtfl fl_orig = std::cout.flags(); fmtfl fl_hex = (fl_orig & ~std::cout.basefield) | std::cout.showbase | std::cout.hex; // . std::cout.flags(fl_hex);
Псевдонимы также работают с указателями функций, но гораздо более удобочитаемыми, чем эквивалентный типдф:
// C++11 using func = void(*)(int); // C++03 equivalent: // typedef void (*func)(int); // func can be assigned to a function pointer value void actual_function(int arg) < /* some code */ >func fptr = &actual_function;
Ограничение typedef механизма заключается в том, что он не работает с шаблонами. Напротив, синтаксис псевдонима типа в C ++11 позволяет создавать шаблоны псевдонимов:
template using ptr = T*; // the name 'ptr' is now an alias for pointer to T ptr ptr_int;
Пример
В следующем примере показано, как использовать шаблон псевдонима с пользовательским механизмом выделения памяти — в данном случае целочисленным векторным типом. Можно заменить любой тип int , чтобы создать удобный псевдоним, чтобы скрыть сложные списки параметров в основном функциональном коде. Используя пользовательский распределитель во всем коде, вы можете улучшить удобочитаемость и снизить риск возникновения ошибок, вызванных опечатками.
#include #include template struct MyAlloc < typedef T value_type; MyAlloc() < >template MyAlloc(const MyAlloc&) < >bool operator==(const MyAlloc&) const < return true; >bool operator!=(const MyAlloc&) const < return false; >T * allocate(const size_t n) const < if (n == 0) < return nullptr; >if (n > static_cast(-1) / sizeof(T)) < throw std::bad_array_new_length(); >void * const pv = malloc(n * sizeof(T)); if (!pv) < throw std::bad_alloc(); >return static_cast(pv); > void deallocate(T * const p, size_t) const < free(p); >>; #include using MyIntVector = std::vector>; #include int main () < MyIntVector foov = < 1701, 1764, 1664 >; for (auto a: foov) std::cout
1701 1764 1664
Определения типов
Объявление typedef вводит имя, которое в область становится синонимом типа, заданного частью объявления типа.
Объявления typedef можно использовать для создания более коротких или более значимых имен для типов, уже определенных языком или типами, объявленными вами. Имена typedef позволяют инкапсулировать детали реализации, которые могут измениться.
В отличие от объявлений class struct и union enum объявлений, объявления typedef не вводят новые типы; они вводят новые имена для существующих типов.
Имена, объявленные с использованием typedef того же пространства имен, что и другие идентификаторы (кроме меток инструкций). Поэтому они не могут использовать тот же идентификатор, что и ранее объявленное имя, за исключением объявления типа класса. Рассмотрим следующий пример:
// typedef_names1.cpp // C2377 expected typedef unsigned long UL; // Declare a typedef name, UL. int UL; // C2377: redefined.
Правила скрытия имен, относящиеся к другим идентификаторам, также управляют видимостью имен, объявленных с помощью typedef . Поэтому следующий код допустим в C++:
// typedef_names2.cpp typedef unsigned long UL; // Declare a typedef name, UL int main() < unsigned int UL; // Redeclaration hides typedef name >// typedef UL back in scope
Другой экземпляр имени скрыт:
// typedef_specifier1.cpp typedef char FlagType; int main() < >void myproc( int )
При объявлении идентификатора локального область с таким же именем, как и typedef при объявлении члена структуры или объединения в том же область или во внутреннем область, необходимо указать описатель типа. Например:
typedef char FlagType; const FlagType x;
Чтобы повторно использовать имя FlagType для идентификатора, члена структуры или члена объединения, необходимо указать тип:
const int FlagType; // Type specifier required
const FlagType; // Incomplete specification
так как принимается FlagType как часть типа, а не идентификатор, который выполняется повторно. Это объявление принимается как незаконное объявление, аналогичное следующему:
int; // Illegal declaration
Можно объявить любой тип с typedef помощью указателя, функции и типов массивов. Имя typedef для типа указателя на структуру или объединение можно объявить до определения типа структуры или объединения, если только определение находится в той же области видимости, что и объявление.
Примеры
Одним из способов использования объявлений является создание объявлений typedef более единообразным и компактным. Например:
typedef char CHAR; // Character type. typedef CHAR * PSTR; // Pointer to a string (char *). PSTR strchr( PSTR source, CHAR target ); typedef unsigned long ulong; ulong ul; // Equivalent to "unsigned long ul;"
typedef Чтобы указать основные и производные типы в одном объявлении, можно разделить деклараторы с запятыми. Например:
typedef char CHAR, *PSTR;
В следующем примере задан тип DRAWF для функции, не возвращающей никакого значения и принимающей два аргумента int.
typedef void DRAWF( int, int );
После приведенной выше typedef инструкции объявление
DRAWF box;
будет эквивалентно следующему:
void box( int, int );
typedef часто объединяется с struct объявлением и именем определяемых пользователем типов:
// typedef_specifier2.cpp #include typedef struct mystructtag < int i; double f; >mystruct; int main()
10 0.990000
Повторная отмена типов
Объявление typedef можно использовать для повторного объявления того же имени, чтобы ссылаться на тот же тип. Например:
Исходный файл file1.h :
// file1.h typedef char CHAR;
Исходный файл file2.h :
// file2.h typedef char CHAR;
Исходный файл prog.cpp :
// prog.cpp #include "file1.h" #include "file2.h" // OK
prog.cpp Файл содержит два файла заголовка, оба из которых содержат typedef объявления для имени CHAR . Если в обеих объявлениях указывается один и тот же тип, такое повторное объявление допустимо.
Не typedef удается переопределить имя, которое ранее было объявлено в качестве другого типа. Рассмотрим эту альтернативу file2.h :
// file2.h typedef int CHAR; // Error
Компилятор выдает ошибку из-за prog.cpp попытки повторного объявления имени CHAR для ссылки на другой тип. Эта политика распространяется на такие конструкции, как:
typedef char CHAR; typedef CHAR CHAR; // OK: redeclared as same type typedef union REGS // OK: name REGS redeclared < // by typedef name with the struct wordregs x; // same meaning. struct byteregs h; >REGS;
typedefs в C++ и C
typedef Использование описателя с типами классов поддерживается в основном из-за практики ANSI C объявления неименованных структур в typedef объявлениях. Например, многие программисты C используют следующую идиому:
// typedef_with_class_types1.cpp // compile with: /c typedef struct < // Declare an unnamed structure and give it the // typedef name POINT. unsigned x; unsigned y; >POINT;
Преимущество такого объявления заключает в том, что можно выполнять объявления
POINT ptOrigin;
struct point_t ptOrigin;
В C++разница между typedef именами и реальными типами (объявленными с class помощью , struct union и enum ключевое слово) более различается. Хотя практика объявления безымяной структуры в typedef инструкции по-прежнему работает, она не предоставляет нотационных преимуществ, как это делает в C.
// typedef_with_class_types2.cpp // compile with: /c /W1 typedef struct < int POINT(); unsigned x; unsigned y; >POINT;
В предыдущем примере объявляется класс с именем с использованием синтаксиса неназванного POINT класса typedef . POINT считается именем класса, однако к именам, предоставленным таким образом, применяются следующие ограничения.
- Имя (синоним) не может отображаться после classstruct префикса или union префикса.
- Имя нельзя использовать в качестве конструктора или деструктора в объявлении класса.
В итоге этот синтаксис не предоставляет никакого механизма для наследования, построения или уничтожения.
Обратная связь
Были ли сведения на этой странице полезными?
Объявления Typedef
Объявление typedef — это объявление с typedef в качестве класса хранения. Декларатор становится новым типом. Объявления typedef можно использовать для создания более коротких или более понятных имен для типов, уже определенных в C, или для объявленных типов. Имена typedef позволяют инкапсулировать детали реализации, которые могут измениться.
Объявление typedef интерпретируется точно так же, как и объявление переменной или функции, но идентификатор становится синонимом типа, а не принимает тип, указанный в объявлении.
Синтаксис
declaration :
declaration-specifiers init-declarator-list необ. ;
declaration-specifiers :
storage-class-specifier declaration-specifiers необ.
type-specifier declaration-specifiers необ.
type-qualifier declaration-specifiers необ.
storage-class-specifier :
typedef
type-specifier :
void
char
short
int
long
float
double
signed
unsigned
struct-or-union-specifier
enum-specifier
typedef-name
Объявление typedef не создает новые типы. Оно создает синонимы для существующих типов или имена для типов, которые могут определяться другими способами. Если имя typedef используется как спецификатор типа, его можно использовать в сочетании с определенными спецификаторами типа (но нельзя использовать с другими спецификаторами). К допустимым модификаторам относятся const и volatile .
Имена typedef используют то же пространство имен, что и обычные идентификаторы. (Дополнительные сведения см. в разделе Пространства имен.) Таким образом, программа может иметь имя typedef и идентификатор локального область с тем же именем. Пример:
typedef char FlagType; int main() < >int myproc( int )
При объявлении идентификатора локального область с тем же именем, что и определение типа, или при объявлении члена структуры или объединения в том же область или во внутренней область, необходимо также указать описатель типа. Следующий пример иллюстрирует это ограничение:
typedef char FlagType; const FlagType x;
Чтобы повторно использовать имя FlagType для идентификатора, члена структуры или члена объединения, необходимо указать тип:
const int FlagType; /* Type specifier required */
const FlagType; /* Incomplete specification */
поскольку FlagType воспринимается как часть типа, а не как заново объявляемый идентификатор. Это объявление недопустимо, как и
int; /* Illegal declaration */
С помощью typedef можно объявить любой тип, включая типы указателя, функции и массива. Имя typedef для типа указателя на структуру или объединение можно объявить до определения типа структуры или объединения, если только определение находится в той же области видимости, что и объявление.
Имена typedef можно использовать, чтобы сделать код более понятным. Все три следующих объявления signal задают один и тот же тип, причем в первом объявлении имена typedef не используются.
typedef void fv( int ), (*pfv)( int ); /* typedef declarations */ void ( *signal( int, void (*) (int)) ) ( int ); fv *signal( int, fv * ); /* Uses typedef type */ pfv signal( int, pfv ); /* Uses typedef type */
Примеры
В следующих примерах показаны объявления typedef:
typedef int WHOLE; /* Declares WHOLE to be a synonym for int */
Например, теперь можно использовать в объявлении переменной, WHOLE такой как WHOLE i; или const WHOLE i; . Однако объявление long WHOLE i; недопустимо.
typedef struct club < char name[30]; int size, year; >GROUP;
Этот оператор объявляет имя GROUP как тип структуры с тремя членами. Поскольку также указан тег структуры, club , в объявлениях можно использовать как имя typedef ( GROUP ), так и тег структуры. Необходимо использовать struct ключевое слово с тегом , а ключевое слово нельзя использовать struct с именем определения типа.
typedef GROUP *PG; /* Uses the previous typedef name to declare a pointer */
Тип PG объявлен как указатель на тип GROUP , который, в свою очередь, определен как тип структуры.
typedef void DRAWF( int, int );
В этом примере задан тип DRAWF для функции, не возвращающей никакого значения и принимающей два аргумента int. Это означает, например, что объявление
DRAWF box;
void box( int, int );
TYPEDEF
Язык С позволяет определять имена новых типов данных с помощью ключевого слова typedef. На самом деле здесь не создается новый тип данных, а определяется новое имя существующему типу. Он позволяет облегчить создание машинно-независимых программ. Единственное, что потребуется при переходе на другую платформу, — это изменить оператор typedef. Он также может помочь документировать код, позволяя назначать содержательные имена стандартным типам данных. Стандартный вид оператора typedef следующий:
typedef тип имя;
где тип — это любой существующий тип данных, а имя — это новое имя для данного типа. Новое имя определяется в дополнение к существующему имени типа, а не замещает его. Например, можно создать новое имя для float, используя
typedef float balance;
Данный оператор сообщает компилятору о необходимости распознавания balance как другого имени для float. Далее можно создать вещественную переменную, используя balance:
Здесь past_due — это вещественная переменная типа balance, другими словами — типа float. Можно использовать typedef для создания имен для более сложных типов. Например:
typedef struct float due;
int over_due;
char name[40];
> client; /* здесь client — это имя нового типа */
client clist[NUM_CLIENTS]; /* определение массива структур типа client */
Использование typedef может помочь при создании более легкого для чтения и более переносимого кода. Но надо помнить, что на самом деле не создаются никакие новые типы данных.
Что такое typedef в C++?
typedef в языке программирования C++ представляет собой ключевое слово, используемое для создания псевдонима (алиаса) для существующего типа данных. Это облегчает работу с длинными и сложными типами, а также повышает читаемость кода.
// Исходный тип данных typedef double Distance; // Использование псевдонима Distance distanceValue = 10.5;
Преимущества использования typedef:
- Улучшение читаемости кода: Создание псевдонимов позволяет использовать более понятные имена для сложных типов данных.
- Повышение поддерживаемости: Использование typedef упрощает изменение типов данных в будущем, поскольку изменения нужно вносить только в одном месте кода.
- Сокращение кода: Псевдонимы уменьшают количество повторяющегося кода, особенно при работе с длинными типами или структурами.