Avant les déclarations de sans nom struct
Bounty question: Donc, ces deux Foo
s ne sont pas la même chose. Des beaux. La deuxième forme est donnée dans une bibliothèque. Comment faire de l'avant-déclarer donné que je ne peux pas le changer?
J'ai toujours pensé que C et C++ permis déclarations répétées à condition qu'il n'y avait pas répété les définitions. Puis je suis tombé sur ce problème lors de la tentative d'écrire du code C++ qui s'étend d'une bibliothèque C.
struct Foo;
typedef struct {} Foo;
Cela donne l'erreur suivante:
'struct Foo' une précédente déclaration en tant que 'struct Foo'
Je veux de l'avant-déclarer, darn it! Quel est le problème ici?
- Quel est le compilateur? Aussi, peut-être le vide déclaration tracasse il?
- Il n'y a pas de langage appelé "C/C++", en particulier dans le contexte de structures. Il y a trop présumé de C++ écrivains à litière "struct" au-dessus de leur code comme il a été 1989.
- il n'y a rien de mal avec
struct
dans le code C++, je l'utilise pour indiquer que je suis en train d'écrire un capsulées type de POD. - Je pense que Kerrek est en se référant à la C "idiome" de ne pas cacher
struct
s derrière untypedef
, au lieu de faire des choses comme nullefoo(struct MyStruct *p);
. - Exactement. Et des choses comme typedef définitions,
typedef struct Foo { /* ... /* } Foo;
.
Vous devez vous connecter pour publier un commentaire.
typedef-ing anonyme struct est une pratique qui remonte avant le C++03 et est principalement orienté afin de conserver la compatibilité avec les pré-C99 compilateurs.
Étant donné que ce n'est qu'en 2011, et que les deux C++ et C sont changé, je me demande pourquoi il n'y a plus up-to-date de la version de cette bibliothèque!
Si elle n'est pas en développement de plus, on ne peut pas "laisser", mais juste "survivre" et le changement c'est la façon de le faire.
S'il est encore en déploiement, soumettre la question à l'équipe de développement.
Si vous avez besoin d'une solution de contournement, de considérer cette structure peut hériter.
Donc, écrire une déclaration anticipée comme
et le définir comme
Et dans tout votre code, oublier
Foo
et toujours utiliserMyFoo
.Vous êtes déclarant deux entités différentes avec le même nom. La première,
struct Foo
, est une structure nomméeFoo
. Le second est un alias pour un anonyme struct.Si vous faire à la place:
Il fonctionne, parce que vous êtes à la déclaration d'une structure nommée
Foo
dans les deux situations.Vous ne pouvez pas déclarer avant anonyme des structures. Vous êtes de gauche avec deux choix: l'ensemble de définition, ou de modifier l'en-tête et le nom de la struct.
Dans une situation similaire, j'ai un héritage d'en-tête C avec quelque chose comme
- Je l'utiliser dans une classe C++ de mon propre, comme paramètre d'une méthode privée:
Pour éviter les #include "old_library.h" de C. php, j'utilise la suite de l'avant de la déclaration:
et dans C.cpp j'ai les déclarations suivantes:
De cette façon, j'utilise C::Foo au lieu de Foo de manière transparente, et n'a pas besoin d'un MyFoo!
Vous n'avez pas besoin de typedef struct en C++:
Si vous voulez l'appeler juste
Foo
au lieu destruct Foo
en C, vous ne besoin de la définition de type, qui peut également être fait de différentes façons:ou
Vous pouvez bien sûr utiliser le formulaire
struct Foo
en C et C++.struct Foo
. (Certains d'entre nous préfèrent le faire de cette façon.)Votre déclaration déclare qu'il y aura un
struct
appeléFoo
.Votre deuxième déclaration est d'une
typedef
appeléFoo
. Ce ne sont pas la même chose.Pour une déclaration de définition de type, vous devez vous référer à la chose qui est typedeffed, donc, comme:
Puisque vous voulez déclarer avant un anonyme struct, vous ne pouvez pas lui donner un nom dans la déclaration de l'entité d'origine, et vous ne pouvez vous y reporter lorsque typedefing il. La "logique" de la syntaxe serait:
Mais puisque ce n'est évidemment pas possible, vous ne pouvez pas déclarer avant anonyme des structures.
Aller standardese, permet d'avoir un coup d'oeil à 9.1-2:
Aucun identifiant, pas de déclaration anticipée.
Ligne de fond de ce: éviter anonyme des structures moins qu'ils vous donnent un avantage que vous avez vraiment besoin.
À mon humble avis, il suffit de changer votre
typedef
à,Il n'y a pas de mal, et il sera toujours compatible dans les deux C & C++. Maintenant, vous pouvez déclarer avant elle.
[Note: Si vous insistez toujours sur de ne pas toucher à la
typedef
à tous, alors voici la sale tour.Cela fonctionne, seulement si
Foo.h
ne contient que des 1struct
déclaration. Je ne recommandons pas il.]typedef struct Foo_struct {} Foo;
qui évite les conflits de nom dans certains des plus anciens compilateurs C et est généralement plus clair quand à essayer de comprendre bizarre erreurs de compilation (est-il de la structure ou de la définition de type qui ne sortes de choses, compilateurs C++ n'ont pas ce problème, mais je pense que c'est encore bon).Votre compilateur peut faire une différence ici.
En utilisant MinGW GCC 3.4.5, les deux déclarations compiler sans erreurs ou des avertissements (en utilisant
-Wall
)et
Est-il possible de l'avant de la déclaration existe déjà à l'intérieur de la bibliothèque? Par exemple, pour permettre une circulaire pointeur:
Si cela existe déjà au sein de la bibliothèque, en-têtes, il serait la cause de l'erreur que vous décrivez.
Je pense que j'ai récemment rencontré le même problème que le posteur d'origine, et ont résolu comme ci-dessous:
Je suis en train d'écrire un wrapper autour d'une tierce partie l'API défini comme:
Foo.h:
Mon wrapper doit avoir Foo en tant que membre, mais je ne veux pas exposer Foo à tous les utilisateurs de mon wrapper.
UberFoo.h:
UberFoo.cpp:
Maintenant, les consommateurs de ma classe peut instancier sans avoir accès à la définition même de _foo/Foo. Ce serait également le travail si j'avais besoin de passer des pointeurs à _foo comme paramètres ou de retour de fonctions ainsi que d'avoir un membre _foo.
main.cpp:
L'astuce ici est de déclarer avant la réelle type struct, pas de typedef avait nom. Notez qu'il est essentiel que la structure de ne pas être anonyme, comme il est courant dans les anciens code C:
Espérons que cette aide!
Vous ne pouvez pas déclarer avant elle, depuis son nom. Ses un sans nom struct, pour qui Foo est un typedef.
Pourquoi ne pas vous juste éviter de l'avant decl.
Si la deuxième définition a été dans un fichier d'en-tête, vous pouvez inclure le fichier d'en-tête première dans votre fichier d'en-tête C++. Pour faire de C++ pense que C de l'en-tête, embrassant #include avec
extern "C" {
et}
doit être suffisant dans la plupart des cas.Vous essayez de définition de type d'un nom précédemment utilisé. La déclaration est parfaitement valide, seulement vous devez utiliser un nom différent.
Noter que la définition de type ne peut pas être utilisé dans la même nom.