Урок №60. Псевдонимы типов: typedef и type alias

  Юрий  | 

    | 

  Обновл. 21 Апр 2019  | 

 12749

 ǀ   6 

В этом уроке мы рассмотрим псевдонимы типов: typedef и type alias.

typedef

Ключевое слово typedef позволяет программисту создать псевдоним для любого типа данных и использовать его вместо фактического имени типа. Чтобы объявить typedef (использовать псевдоним типа) — используйте ключевое слово typedef + тип данных, для которого создаётся псевдоним, а затем, собственно, сам псевдоним. Например:

Обычно, к псевдонимам typedef добавляют окончание «_t», указывая, таким образом, что идентификатором является тип, а не переменная.

typedef не определяет новый тип данных. Это просто псевдоним (другое имя) для уже существующего типа. Его можно использовать везде, где используется обычный тип.

Даже если следующее не имеет смысла, оно всё равно разрешено в C++:

typedef и читабельность кода


typedef используется в улучшении документации и разборчивости кода. Имена типов, такие как char, int, long, double и bool хороши для описания того, какой тип возвращает функция, но чаще всего мы хотим знать, для какой цели служит возвращаемое значение. Например, рассмотрим следующую функцию:

Мы видим, что возвращаемым значением является целое число, но что оно означает? Количество пропущенных вопросов? Идентификационный номер учащегося? Код ошибки? Сам int особо не о чём нам не говорит. Исправим ситуацию:

С использованием возвращаемого типа testScore_t, становится очевидным, что функция возвращает тип, значением которого является результат теста.

typedef и поддержка кода

typedef также позволяет изменить базовый тип объекта без внесения изменений в большое количество кода. Например, если вы использовали тип short для хранения идентификационного номера учащегося, но потом решили, что лучше использовать тип long, то вам придётся прошерстить кучу кода для замены short-а на long. И, вероятно, было бы трудно определить, какой из типов short используется для хранения идентификационных номеров, а какой — для других целей.

С typedef же всё, что вам нужно сделать, это изменить объявление: typedef short studentID_t на typedef long studentID_t. Тем не менее, не стоит забывать об осторожности при изменении типа typedef на тип из другого семейства (например, с int на float или наоборот)! Новый тип данных может иметь проблемы со сравнением или делением целых чисел/чисел типа с плавающей точкой, которые старый тип не имел — об этом следует помнить.

typedef и кроссплатформенность


Ещё одним большим преимуществом typedef является возможность скрывать специфические, для определённых платформ (операционных систем), детали. На некоторых платформах тип int занимает 2 байта, на других — 4 байта. Таким образом, использование типа int для хранения более 2 байтов информации может быть потенциально опасным при написании кроссплатформенного кода.

Поскольку char, short, int и long не указывают свой размер, то для кроссплатформенных программ довольно часто используется typedef для определения псевдонимов, которые включают размер типа данных в битах. Например, int8_t — это 8-битный signed int, int16_t — это 16-битный signed int, а int32_t — это 32-битный signed int.

typedef и упрощение сложного

Хотя мы до сих пор рассматривали только простые типы данных, в C++ вы можете увидеть и следующие переменные/функции:

Писать std::vector<std::pair<std::string, int> > всякий раз, когда нужно использовать этот тип — не очень эффективно и затратно как по времени, так и по приложенным усилиям. Гораздо проще использовать typedef:

Вот! Другое дело! Ведь проще использовать pairlist_t вместо std::vector<std::pair<std::string, int> >, не так ли?

Не переживайте, если вы ещё не знаете, что такое std::vector, std::pair и прочее. Гораздо важнее сейчас усвоить, что с помощью typedef вы можете давать простые имена сложным типам данных, что сделает их проще как для использования, так и для понимания.

type alias


У typedef есть также свои нюансы. Во-первых, легко забыть, что пишется первым: псевдоним типа или имя типа:

Во-вторых, синтаксис typedef становится уже менее привлекательным в связке со сложными типами данных (об этом мы поговорим детальнее, когда будем рассматривать указатели на функции).

Для решения этих проблем, в C++11 ввели новый улучшенный синтаксис для typedef, который имитирует способ объявления переменных. Этот синтаксис называется type alias. С помощью type alias мы пишем имя, которое затем используется как синоним конкретного типа данных (т.е. принцип тот же, но синтаксис более удобен).

Следующий typedef:

В С++11 можно объявить как:

Эти два способа функционально эквивалентны.

Обратите внимание, что хоть мы и используем ключевое слово «using», оно не имеет ничего общего со стейтментами using. Это ключевое слово имеет несколько значений в зависимости от контекста.

Новый синтаксис создания псевдонимов является более чистым при использовании в сложных ситуациях, и его рекомендуется использовать вместо обычного typedef, если ваш компилятор поддерживает C++11.

Правило: Используйте type alias вместо typedef, если ваш компилятор совместим с C++11.

Тест

Задание №1

Используя следующий прототип функции:

Преобразуйте тип возвращаемого значения int в status_t, используя ключевое слово typedef. В ответе к этому заданию укажите стейтмент typedef и обновлённый прототип функции.

Ответ №1

Задание №2

Используя прототип функции из задания №1, преобразуйте тип возвращаемого значения int в status_t, используя ключевое слово using (C++11). В ответе к этому заданию укажите стейтмент создания псевдонима типа и обновлённый прототип функции.

Ответ №2

Оценить статью:

Звёзд: 1Звёзд: 2Звёзд: 3Звёзд: 4Звёзд: 5 (114 оценок, среднее: 4,89 из 5)
Загрузка...

Комментариев: 6

  1. Аватар deb:

    Очень крутой понятный урок.

  2. Аватар Геннадий:

    Цель программиста- выразить вычисления, причем это должно быть сделано:
    -правильно;
    -просто;
    -эффективно.
    (Бьярне Страуструп. "Программирование". Второе издание. стр.156)

  3. Аватар benya:

    Зачем нужен typedef, когда мы можем того же достичь с помощью define?

    1. Аватар Tosha:

      typedef имеет контекст и не конфликтует с другими именами в коде. Например typedef int a; a a = 1; — вполне корректная запись, хоть и извращенная. В объявлении переменной первый идентификатор является ее типом, а второй — именем. Используя макросы, мы бы переписали и тип переменной, и ее имя, что завершилось бы ошибкой компиляции.
      Разумеется, подобное использовать не стоит, я просто попытался показать, что typedef дает больше возможностей. Другой пример — ты можешь использовать в разных пространствах имен одно и то же имя для псевдонима разных типов, более точно отображая смысл своего кода.

      Если возникает идея, что так можно себя больше запутать — стоит вспомнить, что никто не обязует эти возможности использовать. Идеология языка — предоставить инструменты, а правильное и безопасное их использование — это уже забота программиста(Хотя, предупреждения компилятора зачастую помогают избавится от значительной доли потенциальных проблем).

  4. Аватар kmish:

    Добрый день, все понятно и прозрачно.
    Но есть небольшое субъективное замечание, которое мне видится.

    Разве имя функции не должно объяснять, что она возвращает (как Вы ранее писали в одном из уроков)?
    В данном случае, делая псевдоним еще и для типа, получается избыточность. По функции итак отлично понятно, что она результат теста дает и int тут вполне уместен.

Добавить комментарий

Ваш E-mail не будет опубликован. Обязательные поля помечены *