home *** CD-ROM | disk | FTP | other *** search
- Path: sparky!uunet!mcsun!sunic!hagbard!loglule!jbn
- From: jbn@lulea.trab.se (Johan Bengtsson)
- Newsgroups: comp.lang.c++
- Subject: Re: Multiple Header Files Problem
- Message-ID: <5189@holden.lulea.trab.se>
- Date: 11 Nov 92 12:59:26 GMT
- References: <1992Nov10.164547.19059@mprgate.mpr.ca>
- Organization: Telia Research AB, Aurorum 6, 951 75 Lulea, Sweden
- Lines: 82
- X-Newsreader: Tin 1.1 PL4
-
- walduck@mpr.ca (Andrew Walduck) writes:
- : In article <rmartin.721359424@thor> rmartin@thor.Rational.COM (Bob Martin) writes:
- : >A more interesting variation on this issue is the problem of "circular
- : >inclusion". Consider a source file: "a.h" which includes "b.h".
- : >However, "b.h" includes "a.h". This trivial example will fail to
- : >compile. Unless the compiler is very clever (I haven't seen one yet),
- : >it will sit and spin until it exhauses some resouce (usually memory),
- : >and then it will die a horrible death. If it prints an error at all,
- : >the error is nearly certain to have nothing to do with the circular
- : >containment.
- :
- : Why not just wrap your headers in:
- :
- : #ifndef someUniqueIdentiferPerFile_inc
- : #define someUniqueIdentiferPerFile_inc
- :
- : #include <someotherfile.h>
- :
- : // grotty code goes here...
- : #endif
-
- (I'm sure Bob is aware of this idiom)
-
- You still get problems with circularities, although you do not
- cause the compiler to loop forever:
-
- // a.hh
- #ifndef A_HH
- #define A_HH
- #include "b.hh"
- // code for "a", needs stuff in "b.hh"
- #endif
-
- // b.hh
- #ifndef B_HH
- #define B_HH
- #include "a.hh"
- // code for "b", needs stuff in "a.hh"
- #endif
-
- // main.cc
- #include "a.hh"
-
- Problem is that a.hh gets #included, #includes b.hh, which tries to
- #include a.hh. This will fail, since b.hh will not see all declarations
- in a.hh (A_HH is already defined).
-
- In general, circular #includes is a clear indication that you should
- revise your source file structure. Sometimes it is possible to factor out
- a common header file, which both a.hh and b.hh #includes. If a.hh and b.hh
- represent collaborating classes, then it is sometimes useful to create a
- new "broker" class that forwards request between the classes. As Bob said,
- using forward declarations instead of $includes helps too.
-
- B.T.W., you should regularly analyze your #include dependencies not only
- to find circularities, but also for the sake of cleaning up unnecessary
- #includes. If you define the #include patterns during design, you can
- also compare that with what is actually there in the source code.
- The following trivial AWK script is a start:
-
- #!/bin/awk -f
- #
- # includes - AWK script that analyses C/C++ source files
- # Generates output of the form
- #
- # prog.c Includes "interface.h"
- # prog.c Includes <stdio.h>
- # interface.h Includes <string.h>
- #
- /^[ ]*#include/ {
- print FILENAME, "Includes", substr( $2, 2, length($2)-2 )
- ^^^^^
- this is a space and a TAB
-
- Feed it to your favorite graphical layout tool (:-), or use a nice
- environment that provides #include graphs.
-
- --
- --------------------------------------------------------------------------
- | Johan Bengtsson, Telia Research AB, Aurorum 6, S-951 75 Lulea, Sweden |
- | Johan.Bengtsson@lulea.trab.se; Voice:(+46)92075471; Fax:(+46)92075490 |
- --------------------------------------------------------------------------
-