The first rule will fail as soon as circular dependencies appear. Therefore, it can not be applied strictly.
(This can still be made to work, but it replaces most of the work from the programmer to the consumer of these libraries, which is obviously wrong.)
I’m all in favor of rule 2 (although it might be nice to include “direct ad headers” instead of the real deal, as in <iosfwd> , because it reduces compilation time). Actually, I think this is a kind of self-documentation, if the header file “declares” what dependencies it has, and what better way to do this than include the necessary files?
EDIT:
In the comments, I am challenged that circular dependencies between the headers are a sign of poor design and should be avoided.
It is not right. In fact, circular dependencies between classes can be inevitable and are not at all a sign of poor design. The examples are numerous, let me just mention the Observer pattern, which has a circular link between the observer and the subject.
To allow roundness between classes, you should use forward declaration, because the order of declaration matters in C ++. It is now perfectly acceptable to handle this direct declaration in a circular fashion in order to reduce the number of shared files and centralize the code. Of course, the following case does not deserve this scenario, because there is only one forward announcement. However, I worked on a library where it was much more.
// observer.hpp class Observer; // Forward declaration.
// 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
Konrad Rudolph Oct 08 '08 at 9:22 2008-10-08 09:22
source share