最初のルールは、循環依存関係があるとすぐに失敗します。したがって、厳密に適用することはできません。
(これはまだ機能させることができますが、これはプログラマーからこれらのライブラリーの消費者に多くの作業を移すことになり、明らかに間違っています。)
私はすべてルール 2 に賛成です (ただし、実際の処理ではなく、「前方宣言ヘッダー」を含めることは良いかもしれません<iosfwd>
。これにより、コンパイル時間が短縮されるからです)。一般に、ヘッダー ファイルがその依存関係を「宣言」している場合、それは一種の自己文書化であると考えています。これを行うには、必要なファイルをインクルードするよりも良い方法はありません。
編集:
コメントの中で、ヘッダー間の循環依存は悪い設計の兆候であり、避けるべきであることに挑戦しました。
それは正しくありません。実際、クラス間の循環依存は避けられない可能性があり、設計が悪いことを示す兆候ではありません。例は豊富にあります。オブザーバーとサブジェクトの間に循環参照があるオブザーバー パターンについてだけ触れておきます。
クラス間の循環を解決するには、C++ では宣言の順序が重要であるため、前方宣言を使用する必要があります。現在、全体のファイル数を減らし、コードを集中化するために、この前方宣言を循環的に処理することは完全に受け入れられます。確かに、前方宣言が 1 つしかないため、次のケースはこのシナリオには当てはまりません。ただし、これがはるかに多いライブラリに取り組んできました。
// observer.hpp
class Observer; // Forward declaration.
#ifndef MYLIB_OBSERVER_HPP
#define MYLIB_OBSERVER_HPP
#include "subject.hpp"
struct Observer {
virtual ~Observer() = 0;
virtual void Update(Subject* subject) = 0;
};
#endif
// subject.hpp
#include <list>
struct Subject; // Forward declaration.
#ifndef MYLIB_SUBJECT_HPP
#define MYLIB_SUBJECT_HPP
#include "observer.hpp"
struct Subject {
virtual ~Subject() = 0;
void Attach(Observer* observer);
void Detach(Observer* observer);
void Notify();
private:
std::list<Observer*> m_Observers;
};
#endif