En C++, ¿hay alguna diferencia entre:
struct Foo { ... };
y
typedef struct { ... } Foo;
En C++, sólo hay una sutil diferencia. Es un remanente de C, en el que hace una diferencia.
El estándar del lenguaje C (C89 §3.1.2.3, C99 §6.2.3, y C11 §6.2.3) ordena espacios de nombres separados para diferentes categorías de identificadores, incluyendo identificadores de etiqueta (para struct
/union
/enum
) e identificadores ordinarios (para typedef
y otros identificadores).
Si acabas de decir
struct Foo { ... };
Foo x;
obtendrías un error del compilador, porque Foo
sólo está definido en el espacio de nombres de la etiqueta.
Tendrías que declararlo como:
struct Foo x;
Cada vez que quieras referirte a un Foo
, siempre tendrás que llamarlo estructura Foo
. Esto se vuelve molesto rápidamente, así que puedes añadir un typedef
:
struct Foo { ... };
typedef struct Foo Foo;
Ahora la "estructura Foo" (en el espacio de nombres de la etiqueta) y simplemente "Foo" (en el espacio de nombres del identificador ordinario) se refieren a la misma cosa, y puedes declarar libremente objetos de tipo "Foo" sin la palabra clave "estructura".
La construcción:
typedef struct Foo { ... } Foo;
es sólo una abreviatura de la declaración y typedef
.
Finalmente,
typedef struct { ... } Foo;
declara una estructura anónima y crea un typedef
para ella. Así, con esta construcción, no tiene un nombre en el espacio de nombres de la etiqueta, sólo un nombre en el espacio de nombres del typedef. Esto significa que tampoco puede ser declarado hacia adelante. Si quieres hacer una declaración hacia adelante, tienes que darle un nombre en el espacio de nombres de la etiqueta.
En C++, todas las declaraciones struct
/union
/enum
/class
actúan como si estuvieran implícitamente typedef
'ed, siempre que el nombre no esté oculto por otra declaración con el mismo nombre. Ver Michael Burr's answer para los detalles completos.
Hay una diferencia, pero sutil. Míralo así: struct Foo
introduce un nuevo tipo. La segunda crea un alias llamado Foo (y no un nuevo tipo) para un tipo struct
sin nombre.
7.1.3 El especificador typedef**
1 [...]
Un nombre declarado con el especificador typedef se convierte en un typedef-name. Dentro del ámbito de su declaración, un typedef-name es sintácticamente equivalente a una palabra clave y nombra el tipo asociado con el identificador en la forma descrita en la cláusula 8. Un typedef-name es, por tanto, un sinónimo de otro tipo. Un typedef-name no introduce un nuevo tipo como lo hace una declaración de clase (9.1) o una declaración de enum.
8 Si la declaración typedef define una clase (o enum) sin nombre, el primer nombre typedef declarado por la declaración que sea ese tipo de clase (o tipo de enum) se utiliza para denotar el tipo de clase (o tipo de enum) sólo a efectos de enlace (3.5). de enlace (3.5). [Ejemplo:
typedef struct { } *ps, S; // S is the class name for linkage purposes
Así, un typedef siempre se utiliza como marcador de posición/sinónimo de otro tipo.