2009-07-05 11 views
15

En C++, il est possible de créer une struct:Objet du struct, typedef struct, en C++

struct MyStruct 
{ 
    ... 
} 

Et aussi possible de faire ce qui suit:

typedef struct 
{ 
    ... 
} MyStruct; 

Et pourtant, pour autant que je peut dire, aucune différence discernable entre les deux. Lequel est préférable? Pourquoi les deux voies existent-elles s'il n'y a pas de différence? Est-on meilleur que l'autre dans le style ou la lisibilité?

+2

C'est un double de http://stackoverflow.com/questions/612328/difference-between -struct-and-typedef-struct-in-c, mais je ne vais pas voter pour la clôture parce que la réponse acceptée à cette question est (subtilement) erronée, comme expliqué dans la deuxième réponse votée ... –

Répondre

12

La version typedef est un cas particulier de

typedef foo bar; 

qui définit une nouvelle barre "type" comme un alias pour foo. Dans votre cas, foo arrive à être une structure. En C, c'était le seul moyen d'introduire de nouveaux "types" (entre guillemets, car ils ne sont pas vraiment équivalents à int, float et co). En C++, cela n'est pas très utile, car C++ a été conçu pour rendre la définition de nouveaux types plus facile et plus complète que C (au moins au début de C++), et le typedef n'est même pas nécessaire pour se référer à une structure précédemment déclarée (ou classe).

+1

dans ce case foo est aussi une structure sans nom –

+0

Ri ght. et 'MyStruct' sera utilisé à des fins de liaison: Vous trouverez, par exemple, que le compilateur l'utilisera pour filtrer les noms des fonctions membres de celui-ci. –

+0

@David - oui - alors que typedef crée un nom utilisable pour le type sans nom, il y a des conséquences perceptibles à l'utilisation de typedef - voir ma réponse pour plus de détails :) –

2

Vous utiliseriez un typedef afin de ne pas avoir à spécifier le mot-clé struct lors de la déclaration des variables de cette structure.

Sans typedef:

struct MyStruct foo; 

Avec typedef:

MyStruct foo; 

Fondamentalement, vous faites MyStruct apparaissent comme un nouveau type il met également en œuvre un certain niveau d'abstraction de type que les programmeurs ne ont pas besoin de savoir explicitement de quel type il s'agit. Vous pouvez passer MyStruct dans une fonction, manipuler les données qu'il contient et les retourner et le programmeur ne doit jamais s'inquiéter de ce qui se passe réellement.

Une grande partie de la bibliothèque standard C utilise typedefs pour cette raison.

+0

donc son – darkrain

+5

pas besoin de mot-clé 'struct' en C++, seulement C –

+0

Ah désolé, arrive toujours quand les programmeurs C sont impliqués dans des questions C++ :(Mais vous avez attrapé la réponse avant d'avoir fini de l'éditer :) – Cromulent

7

Ce dernier est là pour la compatibilité avec C - utilisez le premier dans le nouveau code C++.

0

La "structure MyStruct {};" Construire définit implicitement le typedef équivalent, donc typiquement ce serait l'usage moderne préféré. Il y a encore quelques utilisations pour un typedef, principalement avec des types de pointeurs pour les structures. Par exemple.

typedef struct MyStruct* MyStructPtr; 
22

Voici les différences entre les deux déclarations/définitions:


1) Vous ne pouvez pas utiliser un nom typedef pour identifier un constructeur ou 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) Vous ne pouvez pas cacher un nom de typedef comme vous le pouvez nom introduit via la tête de classe - ou inversement si vous avez déjà une fonction ou un objet avec un certain nom, vous pouvez toujours déclarer une classe avec ce nom en utilisant la tête de classe mais pas via l'approche 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) Vous ne pouvez pas utiliser un nom de typedef dans un spécificateur de type élaboré

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) Vous ne pouvez pas l'utiliser pour définir imbriquée Structures

struct S { struct M; }; 

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

struct S::M { }; // ok 

Comme vous pouvez le voir, il y a une différence perceptible entre les deux. Certaines des bizarreries de typedefs sont le résultat de la compatibilité C (ce qui explique pourquoi les deux manières existent je crois) - et dans la plupart des cas, déclarer le nom dans la classe est plus naturel C++ - il a ses avantages besoin de définir des constructeurs et des destructeurs), et est donc préférable. Si vous écrivez du code qui doit être compatible C et C++, il est avantageux d'utiliser les deux approches. Mais si vous écrivez du C++ pur, je trouve que spécifier le nom de classe dans la classe-tête soit plus lisible.

+0

Wow! Merci pour cela :) – Viet

+0

Une autre différence serait dans le nom mangling des fonctions au sein de ces structures ou de les recevoir ou des pointeurs comme paramètres. – CesarB

+0

@CesarB - bien par la norme le nom de typedef est utilisé à des fins de liaison si aucun autre nom n'est fourni - donc je ne vois pas en quoi il est différent - peut-être pouvez-vous donner un exemple? –

1

Il existe de nombreuses réponses qui considèrent les deux approches comme équivalentes, mais elles ne le sont pas.

Le mot-clé typedef est utilisé pour créer un alias de type, c'est-à-dire qu'il fournit une nouvelle manière de faire référence à un autre type. Lorsque vous utilisez typedef struct {} XXX; vous créez en fait un type sans nom et ensuite créer un alias XXX à ce type sans nom. D'autre part, lorsque vous tapez struct XXX {}.

S'il vous plaît, lisez la réponse de Michael Burr here (ce qui est une meilleure réponse que celle acceptée pour cette question.