Назначение struct, typedef struct, в С++
В С++ можно создать структуру:
struct MyStruct
{
...
}
А также можно сделать следующее:
typedef struct
{
...
} MyStruct;
И все же, насколько я могу судить, никакой заметной разницы между ними. Что предпочтительнее? Почему оба пути существуют, если нет разницы? Является ли лучше, чем другой по стилю или читабельности?
Ответы
Ответ 1
Версия typedef является частным случаем
typedef foo bar;
который определяет новый "тип" в качестве псевдонима для foo. В вашем случае foo оказывается структурой. В C это был единственный способ ввести новые "типы" (в кавычках, потому что они на самом деле не эквивалентны int, float и co). В С++ это не так полезно, потому что С++ был разработан, чтобы сделать определение новых типов более легким и более полным, чем C (по крайней мере, в начале С++), и typedef даже не нужно ссылаться на ранее объявленную структуру ( или класс).
Ответ 2
Вот различия между двумя объявлениями/определениями:
1) Вы не можете использовать имя typedef для идентификации конструктора или деструктора
struct MyStruct { MyStruct(); ~MyStruct(); }; // ok
typedef struct { MyStructTD(); ~MyStructTD(); } MyStructTD; // not ok
// now consider
typedef struct MyStruct2 { MyStruct2(); } MyStructTD2; // ok
MyStructTD2::MyStruct2() { } // ok
MyStructTD2::MyStructTD2() { } // not ok
2) Вы не можете скрыть имя typedef, например, имя, введенное через class-head, или, наоборот, если у вас уже есть функция или объект с определенным именем, вы все равно можете объявить класс с этим именем, используя class-head, но не с помощью метода typedef.
struct MyStruct { }; // ok
typedef struct { } MyStructTD; // ok
void MyStruct() { } // (1) - ok Hides struct MyStruct
void MyStructTD() { } // (2) - not-ok - ill-formed
//> Or if you flip it around, consider in a new translation unit:
void MyStruct() { } // ok
void MyStructTD() { } // ok
struct MyStruct { }; // ok
typedef struct { } MyStructTD; // Not ok
3) Вы не можете использовать имя typedef в специфицированном спецификаторе типа
struct MyStruct { }; // ok
typedef struct { } MyStructTD; // ok
int main()
{
void MyStruct();
void MyStructTD(); // ok - new declarative region
struct MyStruct ms; // ok - names the type
struct MyStructTD ms2; // not ok - cannot use typedef-name here
}
struct AnotherStruct
{
friend struct MyStruct; // ok
friend struct MyStructTD; // not ok
};
4) Вы не можете использовать его для определения вложенных структур
struct S { struct M; };
typedef struct { } S::M; // not ok
struct S::M { }; // ok
Как вы можете видеть, между ними существует заметная разница. Некоторые из причуд typedefs являются результатом совместимости C (что в основном связано с тем, что оба пути существуют, я считаю) - и в большинстве случаев объявление названия в классе-голове более естественное С++ - оно имеет свои преимущества (особенно когда вы необходимо определить конструкторы и деструкторы), и поэтому предпочтительнее. Если вы пишете код, который должен быть совместимым с C и С++, тогда есть преимущество в использовании обоих подходов. Но если вы пишете чистый С++, я считаю, что определение имени класса в классе-голове должно быть более читаемым.
Ответ 3
Последний существует для совместимости с C - используйте первый в новом коде С++.
Ответ 4
Вы должны использовать typedef, поэтому вам не нужно указывать ключевое слово struct при объявлении переменных этой структуры.
Без typedef:
struct MyStruct foo;
С typedef:
MyStruct foo;
В основном вы создаете MyStruct как новый тип, поэтому он также реализует некоторый уровень абстракции типа, поскольку программистам не нужно явно знать, какой тип он есть. Вы можете передать MyStruct в функцию, манипулировать данными в ней и вернуть ее, и программисту не нужно беспокоиться о том, что на самом деле происходит.
Значительная часть стандартной библиотеки C использует typedefs по этой причине.
Ответ 5
Есть много ответов, которые рассматривают оба подхода как эквивалентные, но они не являются.
Ключевое слово typedef
используется для создания псевдонима типа, то есть оно предоставляет новый способ обращения к другому типу. Когда вы используете typedef struct {} XXX;
, вы фактически создаете неназванный тип, а затем создаете псевдоним XXX для этого неназванного типа. С другой стороны, при вводе struct XXX {}
.
Пожалуйста, прочитайте ответ Michael Burr здесь (это лучший ответ, чем тот, который был принят для этого вопроса.
Ответ 6
"Структура MyStruct {};" Конструкция неявно определяет эквивалентный typedef, поэтому обычно это будет предпочтительным современным использованием. Есть еще некоторые виды использования для typedef, в основном с типами указателей для структур. Например.
typedef struct MyStruct* MyStructPtr;