Avez-vous de bons conseils sur la façon d'éviter dépendances circulaires des fichiers d'en-tête, s'il vous plaît?
Bien sûr, depuis le début, j'essaie de concevoir le projet le plus transparent possible. Cependant, à mesure que de plus en plus de fonctionnalités et de classes sont ajoutées et que le projet devient moins transparent, des dépendances circulaires commencent à se produire.
Existe-t-il des règles générales, vérifiées et fonctionnelles? Merci.
Si vous avez une dépendance circulaire, vous faites quelque chose de mal.
Comme par exemple:
foo.h
-----
class foo {
public:
bar b;
};
bar.h
-----
class bar {
public:
foo f;
};
Est illégal, vous voulez probablement:
foo.h
-----
class bar; // forward declaration
class foo {
...
bar *b;
...
};
bar.h
-----
class foo; // forward declaration
class bar {
...
foo *f;
...
};
Et c'est ok.
Règles générales:
#include "myclass.h"
le premier inclus dans myclass.cpp
.Voici quelques bonnes pratiques que j'utilise pour éviter les dépendances circulaires:
Une approche générale consiste à factoriser les points communs dans un troisième fichier d'en-tête qui est ensuite référencé par les deux fichiers d'en-tête d'origine.
Voir aussi Meilleures pratiques en matière de dépendance circulaire
en fonction de vos capacités de préprocesseur:
#pragma once
ou
#ifndef MY_HEADER_H
#define MY_HEADER_H
your header file
#endif
Si vous trouvez très ennuyeux de concevoir des fichiers d'en-tête, peut-être makeheaders de Hwaci (concepteurs de SQLite et Fossil DVCS) pourrait vous intéresser.
En général, les fichiers d'en-tête doivent déclarer vers l'avant plutôt que d'inclure d'autres en-têtes dans la mesure du possible.
Assurez-vous également de vous en tenir à une classe par en-tête.
Alors vous ne vous tromperez certainement pas.
Le pire couplage provient généralement du code de modèle gonflé. Parce que vous devez inclure la définition dans l'en-tête, cela conduit souvent à inclure tous les types d'en-têtes, puis la classe qui utilise le modèle inclut l'en-tête du modèle, y compris une charge d'autres éléments.
Pour cette raison, je dirais généralement: soyez prudent avec les modèles! Idéalement, un modèle ne devrait rien inclure dans son code d'implémentation.
Ce que vous visez est un approche en couches. Vous pouvez définir des couches où les modules peuvent dépendre des modules des couches inférieures mais l'inverse doit être fait avec observateurs. Maintenant, vous pouvez toujours définir la granularité de vos couches et si vous acceptez la dépendance circulaire au sein des couches, mais dans ce cas, j'utiliserais this .
Altough Artyom a fourni la meilleure réponse, ce tutoriel est également excellent et fournit quelques extensions http://www.cplusplus.com/forum/articles/10627/