45 votes

Déclarations en avant de structures non nommées

Question de prime : Donc, ces deux Foo ne sont pas la même chose. Bien. La deuxième forme est donnée dans une bibliothèque. Comment puis-je le redéclarer étant donné que je ne peux pas le modifier ?


J'ai toujours pensé que le C et le C++ autorisaient les déclarations répétées à condition qu'il n'y ait pas de définitions répétées. J'ai ensuite rencontré ce problème en essayant d'écrire du code C++ qui étend une bibliothèque C.

struct Foo;
typedef struct {} Foo;

Cela donne l'erreur suivante :

La déclaration précédente de 'struct Foo' était 'struct Foo'.

Je veux faire une déclaration préalable, bon sang ! Qu'est-ce qui ne va pas ici ?

41voto

Emilio Garavaglia Points 9189

Le typage des structures anonymes est une pratique qui date d'avant C++03 et qui vise principalement à conserver la compatibilité avec les compilateurs pré-C99.

Étant donné que nous sommes en 2011 et que le C++ et le C ont changé, je me demande pourquoi il n'existe pas de version plus à jour d'une telle bibliothèque !

S'il n'est plus en développement, vous ne pouvez pas "partir", mais simplement "survivre" et le modifier est la façon de faire. S'il est toujours en cours de déploiement, soumettez le problème à l'équipe de développement.

Si vous avez besoin d'une solution de rechange, considérez que struct peut hériter. Ainsi, écrivez une déclaration forward comme

struct MyFoo;

et le définir comme

#include "old_library.h"
struct MyFoo: public Foo {};

Et dans tout votre code, oubliez Foo et utilisez toujours MyFoo .

40voto

Vous déclarez deux entités différentes avec le même nom. La première, struct Foo est une structure nommée Foo . Le second est un alias pour un anonyme struct.

Si vous le faites à la place :

struct Foo;
struct Foo {};

Cela fonctionne, car vous déclarez un struct nommé Foo dans les deux situations.

Vous ne pouvez pas déclarer en avant des structs anonymes. Vous n'avez que deux choix : inclure la définition entière, ou changer l'en-tête et nommer la structure.

13voto

Alex Cohn Points 13248

Dans une situation similaire, j'ai un ancien en-tête C avec quelque chose comme

== old_library.h ==
typedef struct { int data; } Foo;
== /old_library.h ==

Je l'utilise dans une de mes propres classes C++, comme paramètre d'une méthode privée :

class C {
  void run(Foo *ds);
  ...
}

Pour éviter le #include "old_library.h" de C.hpp, j'utilise la déclaration forward suivante :

class C {
  struct Foo;
  void run(Foo *ds);
  ...
}

et dans C.cpp j'ai les déclarations suivantes :

extern "C" {
#include "old_library.h"
}
struct C::Foo : public ::Foo {};

De cette façon, j'utilise C::Foo au lieu de Foo de manière transparente, et je n'ai pas besoin d'un MyFoo !

8voto

molbdnilo Points 9289

Vous n'avez pas besoin de typedef structs en C++ :

struct Foo;     // Forward declaration

struct Foo 
{

}; // Definition

Si vous voulez l'appeler juste Foo au lieu de struct Foo en C, vous faire ont besoin du typedef, ce qui peut aussi être fait de différentes manières :

struct Foo;     /* Forward declaration */

struct Foo /* The name is needed here */
{

}; /* Definition */
typedef struct Foo Foo;  /* typedef */

o

struct Foo;     /* Forward declaration */

typedef struct Foo /* The name is needed here */
{

} Foo; /* Definition and typedef combined */

Vous pouvez bien sûr utiliser le formulaire struct Foo en C et C++.

5voto

Oli Charlesworth Points 148744

Votre déclaration prospective déclare qu'il y aura une struct appelé Foo .

Votre deuxième déclaration est celle d'un typedef appelé Foo . Ce n'est pas la même chose.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X