在c++中,有什么区别:

struct Foo { ... };

and:

typedef struct { ... } Foo;

当前回答

在这篇DDJ文章中,Dan Saks解释了一个小领域,如果你没有对你的结构(和类!)进行类型定义,bug就会蔓延:

If you want, you can imagine that C++ generates a typedef for every tag name, such as typedef class string string; Unfortunately, this is not entirely accurate. I wish it were that simple, but it's not. C++ can't generate such typedefs for structs, unions, or enums without introducing incompatibilities with C. For example, suppose a C program declares both a function and a struct named status: int status(); struct status; Again, this may be bad practice, but it is C. In this program, status (by itself) refers to the function; struct status refers to the type. If C++ did automatically generate typedefs for tags, then when you compiled this program as C++, the compiler would generate: typedef struct status status; Unfortunately, this type name would conflict with the function name, and the program would not compile. That's why C++ can't simply generate a typedef for each tag. In C++, tags act just like typedef names, except that a program can declare an object, function, or enumerator with the same name and the same scope as a tag. In that case, the object, function, or enumerator name hides the tag name. The program can refer to the tag name only by using the keyword class, struct, union, or enum (as appropriate) in front of the tag name. A type name consisting of one of these keywords followed by a tag is an elaborated-type-specifier. For instance, struct status and enum month are elaborated-type-specifiers. Thus, a C program that contains both: int status(); struct status; behaves the same when compiled as C++. The name status alone refers to the function. The program can refer to the type only by using the elaborated-type-specifier struct status. So how does this allow bugs to creep into programs? Consider the program in Listing 1. This program defines a class foo with a default constructor, and a conversion operator that converts a foo object to char const *. The expression p = foo(); in main should construct a foo object and apply the conversion operator. The subsequent output statement cout << p << '\n'; should display class foo, but it doesn't. It displays function foo. This surprising result occurs because the program includes header lib.h shown in Listing 2. This header defines a function also named foo. The function name foo hides the class name foo, so the reference to foo in main refers to the function, not the class. main can refer to the class only by using an elaborated-type-specifier, as in p = class foo(); The way to avoid such confusion throughout the program is to add the following typedef for the class name foo: typedef class foo foo; immediately before or after the class definition. This typedef causes a conflict between the type name foo and the function name foo (from the library) that will trigger a compile-time error. I know of no one who actually writes these typedefs as a matter of course. It requires a lot of discipline. Since the incidence of errors such as the one in Listing 1 is probably pretty small, you many never run afoul of this problem. But if an error in your software might cause bodily injury, then you should write the typedefs no matter how unlikely the error. I can't imagine why anyone would ever want to hide a class name with a function or object name in the same scope as the class. The hiding rules in C were a mistake, and they should not have been extended to classes in C++. Indeed, you can correct the mistake, but it requires extra programming discipline and effort that should not be necessary.

其他回答

不能对typedef结构使用前向声明。

该结构本身是匿名类型,因此没有实际的名称来转发声明。

typedef struct{
    int one;
    int two;
}myStruct;

像这样的前向声明是行不通的:

struct myStruct; //forward declaration fails

void blah(myStruct* pStruct);

//error C2371: 'myStruct' : redefinition; different basic types

一个更重要的区别是:typedef不能前向声明。因此,对于typedef选项,你必须#include包含typedef的文件,这意味着#包含你的.h的所有内容也包括该文件,无论它是否直接需要它,等等。它肯定会影响大型项目的构建时间。

如果没有typedef,在某些情况下,你可以只添加结构Foo的前向声明;在.h文件的顶部,并且在.cpp文件中只有#include结构定义。

在c++中没有区别,但我相信在C中,它会允许你声明结构Foo的实例,而无需显式地执行:

struct Foo bar;

Struct是用来创建数据类型的。 typedef用于为数据类型设置昵称。

在这篇DDJ文章中,Dan Saks解释了一个小领域,如果你没有对你的结构(和类!)进行类型定义,bug就会蔓延:

If you want, you can imagine that C++ generates a typedef for every tag name, such as typedef class string string; Unfortunately, this is not entirely accurate. I wish it were that simple, but it's not. C++ can't generate such typedefs for structs, unions, or enums without introducing incompatibilities with C. For example, suppose a C program declares both a function and a struct named status: int status(); struct status; Again, this may be bad practice, but it is C. In this program, status (by itself) refers to the function; struct status refers to the type. If C++ did automatically generate typedefs for tags, then when you compiled this program as C++, the compiler would generate: typedef struct status status; Unfortunately, this type name would conflict with the function name, and the program would not compile. That's why C++ can't simply generate a typedef for each tag. In C++, tags act just like typedef names, except that a program can declare an object, function, or enumerator with the same name and the same scope as a tag. In that case, the object, function, or enumerator name hides the tag name. The program can refer to the tag name only by using the keyword class, struct, union, or enum (as appropriate) in front of the tag name. A type name consisting of one of these keywords followed by a tag is an elaborated-type-specifier. For instance, struct status and enum month are elaborated-type-specifiers. Thus, a C program that contains both: int status(); struct status; behaves the same when compiled as C++. The name status alone refers to the function. The program can refer to the type only by using the elaborated-type-specifier struct status. So how does this allow bugs to creep into programs? Consider the program in Listing 1. This program defines a class foo with a default constructor, and a conversion operator that converts a foo object to char const *. The expression p = foo(); in main should construct a foo object and apply the conversion operator. The subsequent output statement cout << p << '\n'; should display class foo, but it doesn't. It displays function foo. This surprising result occurs because the program includes header lib.h shown in Listing 2. This header defines a function also named foo. The function name foo hides the class name foo, so the reference to foo in main refers to the function, not the class. main can refer to the class only by using an elaborated-type-specifier, as in p = class foo(); The way to avoid such confusion throughout the program is to add the following typedef for the class name foo: typedef class foo foo; immediately before or after the class definition. This typedef causes a conflict between the type name foo and the function name foo (from the library) that will trigger a compile-time error. I know of no one who actually writes these typedefs as a matter of course. It requires a lot of discipline. Since the incidence of errors such as the one in Listing 1 is probably pretty small, you many never run afoul of this problem. But if an error in your software might cause bodily injury, then you should write the typedefs no matter how unlikely the error. I can't imagine why anyone would ever want to hide a class name with a function or object name in the same scope as the class. The hiding rules in C were a mistake, and they should not have been extended to classes in C++. Indeed, you can correct the mistake, but it requires extra programming discipline and effort that should not be necessary.