J'ai une classe B et je souhaite appeler les membres de la classe A. Ainsi:
1.
//A.h
class B;
class A
{
private:
B* m_p;
};
//a.cpp
#include "B.h"
2.
// A.h
#include "B.h"
class A
{
private:
B * impl_;
};
quelle voie est la meilleure et est-ce que ces deux choses sont similaires quand un petit projet avec peu de dépendance implique?
Votre première façon de faire signifie que, dans a.h
, le existence de class B
est connu, mais pas sa définition . Cela limite ce que vous pouvez faire avec B
dans a.h
. Par exemple, vous pouvez avoir des variables de type B *
, mais pas des variables de type B
(car pour une déclaration d'une variable de type B
, le compilateur doit pouvoir visualiser la définition complète de B
). De même, si vous avez des variables de type B *
, vous ne pouvez pas déréférencer le pointeur (car pour cela également, la définition de B
doit être connue).
Par conséquent, votre deuxième choix - qui ne pose pas ces problèmes - est préférable, et c’est ce que la plupart des gens utilisent la plupart du temps.
Ce ne sont que des cas particuliers dans lesquels la première méthode peut être utile. Par exemple:
.h
comprennent mutuellement (mais vous risquez alors de rencontrer un certain nombre de problèmes supplémentaires, également en ce qui concerne include-gardes; ceci est généralement difficile et à éviter);b.h
est extrêmement volumineux et complexe, évitez de l’inclure autant que possible car cela ralentirait le processus de compilation.Votre première méthode est une déclaration en aval. Votre seconde inclut en fait la classe B.
Quand utiliser l'un sur l'autre?
Réponse: 1.
Regardez http://www.umich.edu/~eecs381/handouts/handouts.html
Directives concernant les fichiers d'en-tête C
Lignes directrices sur les fichiers d'en-tête C++ (par David Kieras, département EECS, Université du Michigan) dit:
Directive n ° 10. Si une déclaration incomplète d'un type X suffira, utilisez il au lieu de # incluant son en-tête X.h. Si une autre structure ou classe Le type X apparaît uniquement en tant que pointeur ou type de référence dans le contenu de un fichier d’en-tête, vous ne devriez pas inclure #include X.h, mais simplement placer un déclaration incomplète de X (également appelée déclaration "en aval") près de le début du fichier d'en-tête, comme dans:
class X;
Voir le document à distribuer Déclarations incomplètes pour plus de discussion sur ce puissant et technique précieuse. Notez que la bibliothèque Standard inclut un en-tête des déclarations incomplètes qui suffisent souvent pour le<iostream>
bibliothèque, nommée<iosfwd>
. #include<iosfwd>
chaque fois que possible, parce que le fichier d'en-tête<iostream>
est extrêmement volumineux (modèles géants!).
Déclarez simplement la classe dans l'en-tête de votre classe A.
class B;
La seconde est meilleure. La classe B
devient un module que vous incluez à l'aide du fichier .h
. Considérons le cas où vous sous-classerez B
à l'avenir et que vous mettez à jour A
pour utiliser C
. Dans le second cas, vous ne remplacez que l'en-tête de #include
et de A
. Dans le premier cas, vous devez modifier la déclaration anticipée. En outre, dans le second cas, vous définissez plus que le symbole B
.
Et comme dans les commentaires, vous devriez utiliser #include "B.h"
si le fichier d’en-tête est dans le même répertoire que le reste du code.
Eh bien, ce que vous faites s'appelle décleration en aval. La raison pour laquelle vous souhaiteriez cela est si vous avez quelque chose comme la classe A qui utilise la classe B et AUSSI la classe B qui utilise la classe A.
Dans le cas où il n’existe qu’une relation, vous pouvez certainement utiliser votre deuxième choix . Si vous avez besoin de la double utilisation, au moins une de vos classes doit utiliser la décélération avant.