Déclaration à terme d'une classe de base
Je suis en train de créer nos propres fichiers d'en-tête qui ne comprennent pas trop d'autres fichiers afin de les garder propres et d'accélérer les temps de compilation.
J'ai rencontré deux problèmes tout en faisant ceci:
- De l'avant de la déclaration sur les classes de base ne fonctionne pas.
class B; class A : public B { //... }
- De l'avant de la déclaration sur les MST classes ne fonctionne pas.
namespace std { class string; } class A { string aStringToTest; }
Comment puis-je résoudre ces problèmes?
source d'informationauteur Tom Wijsman
Vous devez vous connecter pour publier un commentaire.
Le premier problème que vous ne pouvez pas résoudre.
Le deuxième problème n'est pas rien à voir avec le standard de la bibliothèque de classes. C'est parce que vous déclarer une instance de la classe comme un membre de votre propre classe.
Les deux problèmes sont liés à la condition que le compilateur doit être en mesure de trouver la taille totale d'une classe à partir de sa définition.
Cependant, le compilateur peut travailler sur la taille d'un pointeur vers une classe, même si ce n'est pas encore la pleine définition. Donc une solution possible dans ce cas est d'avoir un pointeur (ou de référence) membre dans la classe de consommateurs.
Pas beaucoup d'aide dans la classe de base de cas, parce que vous n'obtiendrez pas de " est une relation.
Ni est-il la peine de le faire pour quelque chose comme
std::string
. Tout d'abord, il est censé être une pratique wrapper autour d'un tampon de caractères, pour vous sauver de faire la gestion de la mémoire sur quelque chose de si simple. Ensuite, si vous maintenez un pointeur vers elle, juste pour éviter d'inclure l'en-tête, vous êtes probablement prendre une bonne idée trop loin.Ensuite (comme l'a fait remarquer dans un commentaire),
std::string
est un typedef pourstd::basic_string<char>
. Donc, vous devez déclarer avant (et utiliser) qui au lieu de cela, les choses deviennent très obscure et difficile à lire, ce qui est un autre type de coût. Est-il vraiment la peine?Comme une réponse avant par Earwicker, vous ne pouvez pas utiliser sa déclaration dans aucun des cas, le compilateur a besoin de savoir la taille de la classe.
Vous ne pouvez utiliser qu'une déclaration anticipée en un ensemble d'opérations:
Vous ne pouvez pas l'utiliser pour
(ai-je oublié?)
Prendre en compte que la déclaration d'une
auto_ptr
n'est pas la même que la déclaration d'un pointeur brut, depuis leauto_ptr
instanciation vais essayer de supprimer le pointeur lorsqu'il est hors de portée et exige la suppression de la déclaration complète de la type. Si vous utilisez unauto_ptr
à tenir un type déclaré de l'avant, vous devrez fournir un destructeur (même vides) et de définir après la déclaration de la classe a été vu.Il y a aussi quelques autres subtilités. Lorsque vous transférez déclarer une classe, vous dire au compilateur qu'il aura une classe. Cela signifie qu'il ne peut pas être un
enum
ou untypedef
en un autre type. C'est le problème que vous obtenez lorsque vous essayez de déclarer avantstd::string
comme c'est une définition de type d'un précis de l'instanciation d'un modèle:À déclarer avant de la chaîne, vous devrez déclarer avant la
basic_string
modèle, puis de créer letypedef
. Le problème est que la norme ne précise pas le nombre de paramètres quebasic_string
modèle prend, c'seulement les etats, que si elle prend plus d'un paramètre, il reste des paramètres doit avoir un type par défaut de sorte que l'expression ci-dessus compile. Cela signifie qu'il n'existe pas de méthode standard pour l'avant de déclarer le modèle.Si, d'autre part, vous souhaitez déclarer un non-modèle standard (non STL, qui est), vous pouvez le faire aussi longtemps que vous savez le nombre de paramètres:
À la fin, de l'avis qui vous a été donnée par Roddy: déclarer avant autant que vous le pouvez, mais partons du principe que certaines choses doivent être inclus.
Que vous essayez trop dur pour résoudre quelque chose qui n'est pas réellement un problème. Utiliser les fichiers d'en-tête dont vous avez besoin, et de réduire dans la mesure du POSSIBLE - l'obligation pour eux. Mais n'essayez pas de le prendre à l'extrême parce que vous allez échouer.
Dans certains cas, le PIMPL idiome peut vous aider, mais pas ici.
Dans les deux cas, le compilateur a besoin de connaître la taille du type. Par conséquent, une déclaration anticipée ne suffira pas. Une classe de base peut ajouter des membres ou exigeant une table virtuelle. La chaîne membre exigeraient la taille de la classe à l'augmentation de mémoriser la taille de la STL classe string.
Avant de déclarer STL classes est souvent déconseillé depuis la mise en œuvre comprennent généralement explicite modèle instanciations d'accélérer la compilation.
Pour vos classes de base, vous devez disposer de l'intégralité de la définition de type, pas seulement une déclaration. Type dérivé en-têtes devront #inclure l'en-tête pour leurs classes de base.
Pour les classes dans l'espace de noms std, vous devez inclure le bon de l'en - tête <string> dans ce cas - puis effectuez l'une des 3 choses:
Entièrement qualifier le type: std::string
aStringToTest
Mettre un à l'aide de déclaration de la juste
type: utilisation de std::string;
Mettre dans une déclaration using pour l'
espace de noms std: using namespace std;
> Semble que l'avant de la déclaration est inutile pour les classes de base et les classes de la stl.
Correction...
Déclaration anticipée est INAPPROPRIÉ pour les classes de base et membre de l'objet. (Ce n'est pas "inutile", c'est "inapplicable".)
Une classe de base DOIT être déclarée (pas avant) lors être déclaré comme une fonction de la classe d'une autre classe.
Un membre de l'objet DOIT être déclarée (pas avant) lors être déclaré par une autre classe, ou comme un paramètre ou une valeur de retour. REMARQUE: par référence ou par pointeur n'ont pas cette contrainte.
Correction...
Avant la déclaration de la STL classes est, selon la norme ISO 14882 -- un comportement indéfini.
http://www.gotw.ca/gotw/034.htm