Verschil tussen 'struct' en 'typedef struct' in C++?

In C++, is er enig verschil tussen:

struct Foo { ... };

en

typedef struct { ... } Foo;
Oplossing

In C++ is er slechts een subtiel verschil. Het is een overblijfsel van C, waarin het een verschil maakt.

De C taal standaard (C89 §3.1.2.3, C99 §6.2.3, en C11 §6.2.3) mandateert aparte namespaces voor verschillende categorieen identifiers, inclusief tag identifiers (voor struct/union/enum) en gewone identifiers (voor typedef en andere identifiers).

Als je gewoon zou zeggen:

struct Foo { ... };
Foo x;

zou je een compilerfout krijgen, omdat Foo alleen in de tag namespace gedefinieerd is.

Je'zou het moeten declareren als:

struct Foo x;

Elke keer als je naar een Foo wilt verwijzen, moet je het altijd een struct Foo noemen. Dit wordt snel vervelend, dus je kunt een typedef toevoegen:

struct Foo { ... };
typedef struct Foo Foo;

Nu verwijzen struct Foo (in de tag namespace) en gewoon Foo (in de gewone identifier namespace) allebei naar hetzelfde, en kun je objecten van het type Foo vrij declareren zonder het struct keyword.


De construct:

typedef struct Foo { ... } Foo;

is gewoon een afkorting voor de declaratie en typedef.


Tenslotte,

typedef struct { ... } Foo;

declareert een anonieme structuur en creëert er een typedef voor. Met deze constructie heeft het dus geen naam in de tag namespace, maar alleen een naam in de typedef namespace. Dit betekent dat het ook niet forward-declared kan worden. Als je een forward-declared wilt maken, moet je het een naam geven in de tag namespace.


In C++ gedragen alle struct/union/enum/class declaraties zich alsof ze impliciet typedef'ed zijn, zolang de naam niet verborgen wordt door een andere declaratie met dezelfde naam. Zie Michael Burr's antwoord voor de volledige details.

Commentaren (16)

Er is een verschil, maar subtiel. Bekijk het zo: struct Foo introduceert een nieuw type. De tweede creëert een alias genaamd Foo (en niet een nieuw type) voor een naamloos struct type.

7.1.3 De typedef specificier

1 [...]

Een naam gedeclareerd met de typedef specifier wordt een typedef-naam. Binnen het bereik van zijn declaratie is een typedef-naam syntactisch gelijkwaardig aan een sleutelwoord en benoemt het type dat geassocieerd is met de identifier op zoals beschreven in clausule 8. Een typedef-naam is dus een synoniem voor een ander type. Een typedef-naam introduceert geen nieuw type zoals een klasse-declaratie (9.1) of enum-declaratie dat doet.

8 Als de typedef-declaratie een naamloze klasse (of enum) definieert, zal de eerste typedef-naam die door de declaratie als dat klassentype (of enumtype) wordt gebruikt om het klassentype (of enumtype) aan te duiden voor koppelings alleen voor koppelingsdoeleinden (3.5). [Voorbeeld:

typedef struct { } *ps, S; // S is the class name for linkage purposes

Een typedef wordt dus altijd gebruikt als een placeholder/synoniem voor een ander type.

Commentaren (0)

Er is geen verschil in C++, maar ik geloof dat je in C instanties van de struct Foo kunt declareren zonder het expliciet te doen:

struct Foo bar;
Commentaren (1)