Как определить синоним типа с помощью typedef
Директива typedef позволяет задать синоним для встроенного либо пользовательского типа данных. Например:
Имена, определенные с помощью директивы typedef, можно использовать точно так же, как спецификаторы типов:
Эта директива начинается с ключевого слова typedef, за которым идет спецификатор типа, и заканчивается идентификатором, который становится синонимом для указанного типа.
Для чего используются имена, определенные с помощью директивы typedef? Применяя мнемонические имена для типов данных, можно сделать программу более легкой для восприятия. Кроме того, принято употреблять такие имена для сложных составных типов, в противном случае воспринимаемых с трудом (см. пример в разделе 3.14), для объявления указателей на функции и функции-члены класса (см. раздел 13.6).
Ниже приводится пример вопроса, на который почти все дают неверный ответ. Ошибка вызвана непониманием директивы typedef как простой текстовой макроподстановки. Дано определение:
typedef char *cstring;
Каков тип переменной cstr в следующем объявлении:
extern const cstring cstr;
Ответ, который кажется очевидным:
Однако это неверно. Спецификатор const относится к cstr, поэтому правильный ответ – константный указатель на char:
Источник статьи: http://mycpp.ru/cpp/book/c03_12.html
Псевдонимы и определения типов (C++) Aliases and typedefs (C++)
Объявление псевдонима можно использовать для объявления имени, которое будет использоваться в качестве синонима для ранее объявленного типа. You can use an alias declaration to declare a name to use as a synonym for a previously declared type. (Этот механизм также называется псевдонимом типа). (This mechanism is also referred to informally as a type alias). Этот механизм также можно использовать для создания шаблона псевдонима, который может быть особенно полезен для пользовательских распределительов. You can also use this mechanism to create an alias template, which can be particularly useful for custom allocators.
Синтаксис Syntax
Remarks Remarks
identifier identifier
Имя псевдонима. The name of the alias.
type type
Идентификатор типа, для которого создается псевдоним. The type identifier you are creating an alias for.
Псевдоним не вводит в программу новый тип и не может менять значение существующего имени типа. An alias does not introduce a new type and cannot change the meaning of an existing type name.
Простейшая форма псевдонима эквивалентна typedef механизму из c++ 03: The simplest form of an alias is equivalent to the typedef mechanism from C++03:
Оба этих механизма позволяют создавать переменные типа «счетчик». Both of these enable the creation of variables of type «counter». Псевдоним типа для std::ios_base::fmtflags , приведенный в следующем примере, может быть более полезен. Something more useful would be a type alias like this one for std::ios_base::fmtflags :
Псевдонимы также работают с указателями на функции, но гораздо удобнее для чтения, чем эквивалентное определение типа: Aliases also work with function pointers, but are much more readable than the equivalent typedef:
Ограничением typedef механизма является то, что оно не работает с шаблонами. A limitation of the typedef mechanism is that it doesn’t work with templates. Напротив, синтаксис псевдонима типа в C ++11 позволяет создавать шаблоны псевдонимов: However, the type alias syntax in C++11 enables the creation of alias templates:
Пример Example
В следующем примере показано, как использовать шаблон псевдонима с пользовательским механизмом выделения памяти — в данном случае целочисленным векторным типом. The following example demonstrates how to use an alias template with a custom allocator—in this case, an integer vector type. Вы можете заменить любой тип на int , чтобы создать удобный псевдоним для скрытия сложных списков параметров в основном функциональном коде. You can substitute any type for int to create a convenient alias to hide the complex parameter lists in your main functional code. Применяя по всему коду пользовательские механизмы выделения памяти, можно повысить удобочитаемость и уменьшить риск возникновения ошибок, связанных с опечатками. By using the custom allocator throughout your code you can improve readability and reduce the risk of introducing bugs caused by typos.
Определения типов Typedefs
typedef Объявление вводит имя, которое в пределах его области видимости преобразуется в синоним для типа, заданного в объявлении типа . A typedef declaration introduces a name that, within its scope, becomes a synonym for the type given by the type-declaration portion of the declaration.
Объявления typedef можно использовать для создания более коротких или более понятных имен для типов, уже определенных в языке или объявленных пользователем. You can use typedef declarations to construct shorter or more meaningful names for types already defined by the language or for types that you have declared. Имена typedef позволяют инкапсулировать детали реализации, которые могут измениться. Typedef names allow you to encapsulate implementation details that may change.
В отличие от class объявлений, struct , union и enum , typedef объявления не предоставляют новые типы — они представляют новые имена для существующих типов. In contrast to the class , struct , union , and enum declarations, typedef declarations do not introduce new types — they introduce new names for existing types.
Имена, объявленные с помощью typedef , занимают то же пространство имен, что и другие идентификаторы (кроме меток операторов). Names declared using typedef occupy the same namespace as other identifiers (except statement labels). Таким образом, в них не может использоваться тот же идентификатор, что и в объявленном ранее имени, за исключением случаев, когда они находятся в объявлении типа класса. Therefore, they cannot use the same identifier as a previously declared name, except in a class-type declaration. Рассмотрим следующий пример: Consider the following example:
Правила скрытия имен, относящиеся к другим идентификаторам, также управляют видимостью имен, объявленных с помощью typedef . The name-hiding rules that pertain to other identifiers also govern the visibility of names declared using typedef . Поэтому следующий код допустим в C++: Therefore, the following example is legal in C++:
При объявлении в локальной области идентификатора с тем же именем, что и имя typedef, или при объявлении члена структуры либо объединения в той же области или во внутренней области обязательно должен указываться спецификатор типа. When declaring a local-scope identifier by the same name as a typedef, or when declaring a member of a structure or union in the same scope or in an inner scope, the type specifier must be specified. Например: For example:
Чтобы повторно использовать имя FlagType для идентификатора, члена структуры или члена объединения, необходимо указать тип: To reuse the FlagType name for an identifier, a structure member, or a union member, the type must be provided:
Недостаточно написать It is not sufficient to say
поскольку FlagType воспринимается как часть типа, а не как заново объявляемый идентификатор. because the FlagType is taken to be part of the type, not an identifier that is being redeclared. Это объявление недопустимо, как и This declaration is taken to be an illegal declaration like
С помощью typedef можно объявить любой тип, включая типы указателей, функций и массивов. You can declare any type with typedef, including pointer, function, and array types. Имя typedef для типа указателя на структуру или объединение можно объявить до определения типа структуры или объединения, если только определение находится в той же области видимости, что и объявление. You can declare a typedef name for a pointer to a structure or union type before you define the structure or union type, as long as the definition has the same visibility as the declaration.
Примеры Examples
Использование typedef объявлений состоит в том, чтобы сделать объявления более однородными и компактными. One use of typedef declarations is to make declarations more uniform and compact. Например: For example:
Чтобы использовать typedef для указания фундаментальных и производных типов в одном объявлении, можно разделить деклараторы запятыми. To use typedef to specify fundamental and derived types in the same declaration, you can separate declarators with commas. Например: For example:
В следующем примере задан тип DRAWF для функции, не возвращающей никакого значения и принимающей два аргумента int. The following example provides the type DRAWF for a function returning no value and taking two int arguments:
После оператора выше typedef объявление After the above typedef statement, the declaration
будет эквивалентно следующему: would be equivalent to the declaration
typedef часто объединяется с struct для объявления и именования определяемых пользователем типов: typedef is often combined with struct to declare and name user-defined types:
Повторное объявление определений типов Re-declaration of typedefs
typedef Объявление можно использовать для повторного объявления того же имени для ссылки на один и тот же тип. The typedef declaration can be used to redeclare the same name to refer to the same type. Например: For example:
Программа Prog. CPP включает два файла заголовка, оба из которых содержат typedef объявления для имени CHAR . The program PROG.CPP includes two header files, both of which contain typedef declarations for the name CHAR . Если в обеих объявлениях указывается один и тот же тип, такое повторное объявление допустимо. As long as both declarations refer to the same type, such redeclaration is acceptable.
typedef Невозможно переопределить имя, которое ранее было объявлено как другой тип. A typedef cannot redefine a name that was previously declared as a different type. Таким образом, если file2. H содержит Therefore, if FILE2.H contains
компилятор выдает ошибку из-за попытки повторного объявления имени CHAR как имени другого типа. the compiler issues an error because of the attempt to redeclare the name CHAR to refer to a different type. Это правило распространяется также на конструкции, подобные следующим: This extends to constructs such as:
определения типов в C++ и C typedefs in C++ vs. C
Использование typedef спецификатора с типами классов в основном поддерживается из-за объявления неименованных структур в объявлениях в ANSI C typedef . Use of the typedef specifier with class types is supported largely because of the ANSI C practice of declaring unnamed structures in typedef declarations. Например, многие программисты C используют следующий код. For example, many C programmers use the following:
Преимущество такого объявления заключает в том, что можно выполнять объявления The advantage of such a declaration is that it enables declarations like:
В C++ разница между typedef именами и реальными типами (объявленными с class struct union enum ключевыми словами,, и) более Разна. In C++, the difference between typedef names and real types (declared with the class , struct , union , and enum keywords) is more distinct. Хотя методика C объявления структуры без имени в typedef инструкции по-прежнему работает, она не предоставляет преимуществ для нотаций, как это делается в c. Although the C practice of declaring a nameless structure in a typedef statement still works, it provides no notational benefits as it does in C.
В предыдущем примере объявляется класс с именем POINT с использованием синтаксиса неименованного класса typedef . The preceding example declares a class named POINT using the unnamed class typedef syntax. POINT считается именем класса, однако к именам, предоставленным таким образом, применяются следующие ограничения. POINT is treated as a class name; however, the following restrictions apply to names introduced this way:
Имя (синоним) не может использоваться после class struct union префикса, или. The name (the synonym) cannot appear after a class , struct , or union prefix.
Имя не может использоваться в качестве имени конструктора или деструктора в объявлении класса. The name cannot be used as constructor or destructor names within a class declaration.
Таким образом, этот синтаксис не предоставляет механизм наследования, создания или удаления. In summary, this syntax does not provide any mechanism for inheritance, construction, or destruction.
Источник статьи: http://docs.microsoft.com/ru-ru/cpp/cpp/aliases-and-typedefs-cpp?view=vs-2017