2009-07-05 22 views
15

En C++ es posible crear una estructura:Propósito de la estructura, typedef struct, en C++

struct MyStruct 
{ 
    ... 
} 

Y también es posible hacer lo siguiente:

typedef struct 
{ 
    ... 
} MyStruct; 

Y sin embargo, en lo que a puede decir, sin diferencia discernible entre los dos. ¿Cuál es preferible? ¿Por qué existen ambas formas si no hay diferencia? ¿Es uno mejor que el otro en estilo o legibilidad?

+2

Este es un duplicado de http://stackoverflow.com/questions/612328/difference-between -struct-and-typedef-struct-in-c, pero no voy a votar a favor del cierre porque la respuesta aceptada a esa pregunta es (sutilmente) incorrecta, como se explica en la respuesta del segundo voto ... –

Respuesta

12

La versión typedef es un caso especial de

typedef foo bar; 

que define una nueva barra de "tipo" como un alias para foo. En tu caso, foo resulta ser una estructura. En C, esta era la única forma de introducir nuevos "tipos" (entre comillas, porque no son realmente equivalentes a int, float y co). En C++, esto no es tan útil, porque C++ se diseñó para hacer más fácil y más completa la definición de nuevos tipos que C (al menos en los comienzos de C++), y el typedef ni siquiera es necesario para referirse a una estructura previamente declarada (o clase).

+1

en este caso foo también es una estructura sin nombre –

+0

Ri GHT y 'MyStruct' se usará para fines de vinculación: encontrará, por ejemplo, que el compilador lo usará para modificar los nombres de las funciones miembro de él. –

+0

@David - sí - mientras typedef crea un nombre utilizable para el tipo sin nombre, hay consecuencias discernibles para el uso de typedef - ver mi respuesta para más detalles :) –

2

Utilizaría un typedef por lo que no necesita especificar la palabra clave struct al declarar las variables de esa estructura.

Sin typedef:

struct MyStruct foo; 

Con typedef:

MyStruct foo; 

Básicamente usted está haciendo MyStruct aparece como un nuevo tipo por lo que también implementa un cierto nivel de tipo de abstracción que los programadores no necesitan saber explícitamente qué tipo es. Puede pasar MyStruct a una función, manipular los datos que contiene y devolverlos, y el programador nunca tendrá que preocuparse por lo que realmente sucede.

Gran parte de la biblioteca estándar C usa typedefs por este motivo.

+0

por lo que simplemente escribiendo menos? – darkrain

+5

sin necesidad de palabra clave 'struct' en C++, solo C –

+0

Ah, lo siento, siempre sucede cuando los programadores C se involucran en C++ preguntas :(. Pero captó la respuesta antes de terminar de editarlo :). – Cromulent

7

Lo último está ahí para la compatibilidad con C: utilice el primero en el nuevo código de C++.

0

La "struct MyStruct {};" constructo define implícitamente el typedef equivalente, por lo que normalmente sería el uso moderno preferido. Todavía hay algunos usos para un typedef, principalmente con tipos de puntero a estructuras. P.ej.

typedef struct MyStruct* MyStructPtr; 
22

Estas son las diferencias entre las dos declaraciones/definiciones:


1) No puede utilizar un nombre typedef para identificar un constructor o un destructor

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) No puede ocultar un tipo de nombre como puede nombre introducido a través del encabezado de clase - o por el contrario si ya tiene una función o un objeto con un cierto nombre, todavía puede declarar una clase con ese nombre utilizando el encabezado de clase pero no a través del enfoque 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) No se puede utilizar un nombre typedef en un especificador de tipo elaborado

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) No se puede utilizar para definir anidada construye

struct S { struct M; }; 

typedef struct { } S::M; // not ok 

struct S::M { }; // ok 

Como se puede ver, hay una diferencia apreciable entre los dos. Algunas de las peculiaridades de typedefs son el resultado de la compatibilidad C (que es principalmente la razón por la que ambas formas creo) y, en la mayoría de los casos, declarar el nombre en el encabezado de clase es más natural que C++, tiene sus ventajas (especialmente cuando necesidad de definir constructores y destructores), y por lo tanto es preferible. Si está escribiendo código que necesita ser compatible con C y C++, entonces se beneficia el uso de ambos enfoques. Pero si estás escribiendo C++ puro, encuentro que especificar el nombre de clase en el encabezado de clase es más legible.

+0

¡Guau! Gracias por esto :) – Viet

+0

Otra diferencia sería en el cambio de nombre de las funciones dentro de estas estructuras o recibirlas o punteros a ellas como parámetros. – CesarB

+0

@CesarB: bueno, según el estándar, el nombre typedef se usa para fines de vinculación si no se proporciona otro nombre, por lo que no veo cómo es diferente, ¿quizás puede proporcionar un ejemplo? –

1

Hay muchas respuestas que consideran que ambos enfoques son equivalentes, pero no lo son.

La palabra clave typedef se utiliza para crear un alias de tipo, es decir, proporciona una nueva forma de referirse a otro tipo. Cuando usa typedef struct {} XXX;, en realidad está creando un tipo sin nombre y luego creando un alias XXX para ese tipo de nombre. Por otro lado, cuando escribe struct XXX {}.

Por favor, lee la respuesta de Michael Burr here (que es una respuesta mejor que la aceptada por esa pregunta.