Purpose of struct, typedef struct, in C++
在C++中,可以创建一个结构:
1 2 3 4 | struct MyStruct { ... } |
也可以执行以下操作:
1 2 3 4 | typedef struct { ... } MyStruct; |
但据我所知,两者之间没有明显的区别。哪个更好?如果没有区别,为什么两者都存在?在样式或可读性方面,一个比另一个好吗?
以下是两种声明/定义之间的区别:
1) You cannot use a typedef name to identify a constructor or a destructor
1 2 3 4 5 6 7 8 9 | 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) You cannot hide a typedef name like you can a name introduced via the class-head - or conversely if you already have a function or an object with a certain name, you can still declare a class with that name using the class-head but not via the typedef approach.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | 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) You cannot use a typedef name in an elaborated type specifier
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | 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) You cannot use it to define nested structs
1 2 3 4 5 | struct S { struct M; }; typedef struct { } S::M; // not ok struct S::M { }; // ok |
正如你所看到的,两者之间有着明显的区别。Type的一些怪癖是C兼容性的结果(这主要是为什么我相信这两种方式)-并且在大多数情况下,在类头中声明名称更自然的C++——它有它的优势(特别是当你需要定义构造函数和析构函数)时,因此是可取的。如果您编写的代码需要是C和C++兼容的,那么使用这两种方法都是有益的。但是如果您编写纯C++,我发现指定类头中的类名更可读。
typedef版本是
1 | typedef foo bar; |
它将新的"类型"栏定义为foo的别名。在您的例子中,foo恰好是一个结构。在C语言中,这是引入新"类型"的唯一方法(在引号中,因为它们实际上并不等同于int、float和co)。在C++中,这并不是很有用,因为C++被设计成使新类型的定义比C更容易和更完整(至少在C++开始时),并且TyPIFF甚至不需要引用先前声明的结构(或类)。
后者与C兼容,使用新C++代码中的第一个。
您将使用typedef,因此在声明该结构的变量时不需要指定struct关键字。
不带typedef:
1 | struct MyStruct foo; |
使用TyPulf:
1 | MyStruct foo; |
基本上,您使mystruct看起来是一种新类型,因此它也实现了某种级别的类型抽象,因为程序员不需要明确地知道它是什么类型。你可以将mystruct传递到一个函数中,操纵函数中的数据并返回它,程序员不必担心实际发生的事情。
因此,许多C标准库都使用typedef。
有许多答案认为这两种方法都是等效的,但事实并非如此。
请在这里读一下迈克尔·伯尔的回答(这比那个问题的答案更好)。
"struct mystruct"结构隐式定义了等效typedef,因此通常这是首选的现代用法。typedef还有一些用途,主要是用于结构的指针类型。例如。
1 | typedef struct MyStruct* MyStructPtr; |