Haben Sie einen guten Rat, wie Sie zirkuläre Abhängigkeiten von Header-Dateien vermeiden können?
Natürlich versuche ich von Anfang an, das Projekt so transparent wie möglich zu gestalten. Da jedoch immer mehr Features und Klassen hinzugefügt werden und das Projekt weniger transparent wird, treten kreisförmige Abhängigkeiten auf.
Gibt es allgemeine, überprüfte und funktionierende Regeln? Danke.
Wenn Sie Kreislaufabhängigkeit haben, dann tun Sie etwas falsch.
Wie zum Beispiel:
foo.h
-----
class foo {
public:
bar b;
};
bar.h
-----
class bar {
public:
foo f;
};
Ist illegal, was Sie wahrscheinlich wollen:
foo.h
-----
class bar; // forward declaration
class foo {
...
bar *b;
...
};
bar.h
-----
class foo; // forward declaration
class bar {
...
foo *f;
...
};
Und das ist in Ordnung.
Allgemeine Regeln:
#include "myclass.h"
das erste include in myclass.cpp
.Einige Best Practices, die ich befolge, um zirkuläre Abhängigkeiten zu vermeiden, sind:
Ein allgemeiner Ansatz besteht darin, die Gemeinsamkeiten in eine dritte Header-Datei zu zerlegen, auf die dann von den beiden ursprünglichen Header-Dateien verwiesen wird.
Siehe auch Circular Dependency Best Practice
abhängig von Ihren Präprozessor-Fähigkeiten:
#pragma once
oder
#ifndef MY_HEADER_H
#define MY_HEADER_H
your header file
#endif
Wenn Sie es sehr langweilig finden, Header-Dateien zu entwerfen, könnte makeheaders von Hwaci (Designer von SQLite und Fossil DVCS) für Sie von Interesse sein.
Im Allgemeinen sollten Header-Dateien nach Möglichkeit vorwärts deklarieren, anstatt andere Header einzuschließen.
Stellen Sie außerdem sicher, dass Sie sich an eine Klasse pro Header halten.
Dann werden Sie mit ziemlicher Sicherheit nichts falsch machen.
Die schlechteste Kopplung entsteht normalerweise durch aufgeblähten Vorlagencode. Da Sie die Definition in den Header einfügen müssen, müssen häufig alle Arten von Headern eingefügt werden, und dann enthält die Klasse, die die Vorlage verwendet, den Vorlagenheader, einschließlich einer Menge anderer Elemente.
Aus diesem Grund würde ich generell sagen: Vorsicht mit Vorlagen! Im Idealfall sollte eine Vorlage nichts in den Implementierungscode aufnehmen müssen.
Was Sie anstreben, ist ein überlagerter Ansatz. Sie können Ebenen definieren, in denen Module von Modulen niedrigerer Ebenen abhängen können. Die Umkehrung sollte jedoch mit Beobachter erfolgen. Jetzt können Sie noch definieren, wie feinkörnig Ihre Ebenen sein sollen und ob Sie kreisförmige Abhängigkeiten innerhalb von Ebenen akzeptieren. In diesem Fall würde ich jedoch this verwenden.
Obwohl Artyom die beste Antwort geliefert hat, ist dieses Tutorial auch großartig und bietet einige Erweiterungen http://www.cplusplus.com/forum/articles/10627/