home *** CD-ROM | disk | FTP | other *** search
- Path: sparky!uunet!olivea!charnel!rat!usc!zaphod.mps.ohio-state.edu!cs.utexas.edu!convex!egsner!adaptex!sdf!carden
- From: carden@sdf.lonestar.org (Jack Carden)
- Newsgroups: comp.lang.c++
- Subject: Re: Idempotent header file proposal
- Summary: alternate proposal
- Keywords: alternative ideas header file organization
- Message-ID: <Bz0xp6.E8H@sdf.lonestar.org>
- Date: 10 Dec 92 03:29:29 GMT
- Followup-To: comp.lang.c++
- Organization: sdf full-shell Public Access Unix - Dallas, TX - 214/436-3281
- Lines: 133
-
- In article <1992Nov19.090742.23696@cbfsb.cb.att.com> nh@cbnewsg.cb.att.com (nicholas.hounsome) writes:
- |One problem with C++ is that when used properly it requires huge
- |numbers of header files most of which are included multiple times.
- |Of course I know that there is the crude workaround :
- |
- |#ifndef HEADER_H
- |#define HEADER_H
- |
- |stuff
- |
- |#endif
- |
- |But the preprocessor still has to find, open , and read the whole file
- |so it does not realy gain you any efficiency.
-
- Please allow me to add another idea to this discussion. While attending
- the USENIX C++ Conference, in Denver, 1988, I heard an attendee explain
- his method for controlling include file use. I am sorry that I can't
- give proper credit to this person, but I liked his ideas so much that I
- adopted them then and have used them since in all the development projects
- I have tackled. I still like this approach better than precompiled header
- files (unless I would gain confidence that the preprocessor "understands"
- my class relationships.)
-
- The approach requires some discipline in header file creation, but I
- haven't found this to be a problem. One begins with the idea of a master
- include file for the project or the component to be created. The master
- include file will include all other required files, but only those required
- in the particular "module" under compilation. The master file will know
- which files to include because the author has used #define to indicate
- required files (generally one class per include file.)
-
- The individual class include files will generally look like this:
-
- == classA.h ==
- #ifndef Pass2 // test for appropriate "pass" on this file
- #define Incl_classB // indicate the need for classB definitions
- #else // otherwise proceed with classA definitions
-
- class classA {
- protected:
- void foo(classB &);
- ...
- };
- #endif
-
-
- == classB.h ==
- #ifndef Pass2
- #define Incl_classC
- #define Incl_assert // can also indicate the need for standard include files
- #else
-
- class classB : public classC {
- ...
- };
- #endif
-
- The master include file will generally look like this:
-
- == master.h ==
- // begin first pass of all project-related include files
- #ifdef Incl_classA // inclusion of classA preceeds classB because of dependency
- #include "classA.h"
- #endif
-
- ...
-
- #ifdef Incl_classB // inclusion of classB preceeds classC because of dependency
- #include "classB.h"
- #endif
-
- ...
-
- #ifdef Incl_classC // inclusion of classC follows classA and classB
- #include "classC.h"
- B
- #endif
-
- ...
-
- // include any "standard" include files as requested
- #ifdef Incl_assert
- #include <assert.h>
- #endif
-
- // begin second pass of all project-related include files.
- // Note the inverted order of inclusion.
- #define Pass2
- #ifdef Incl_classC // inclusion of classC lays the foundation for classA and classB
- #include "classC.h"
- #endif
-
- ...
-
- #ifdef Incl_classB // inclusion of classB preceeds classA because of dependency
- #include "classB.h"
- #endif
-
- ...
-
- #ifdef Incl_classA // inclusion of classA follows classB because of dependency
- #include "classA.h"
- #endif
-
- All source files will generally look like this:
- == classA.C
- #define Incl_classA // indicate the need for classA definitions.
- #define Incl_classB // we can also request any others we want.
- // we assume that classA may request others.
- #define Incl_classD // we might require other classes as well.
- #include "master.h"
-
- void classA::
- foo(classB &)
- {
- ...
- }
-
- This organization seems to provide two benefits:
- 1) It forces the organization of include files to be consistent and
- it causes the designer to consider the appropriate order for
- inclusion in master.h thereby prohibiting circular references.
- 2) It limits the pre-processor to two scans of each of the include files
- for each compilation.
-
- Are there over-simplifications that I have missed? This approach has
- proven very satisfactory (at least in my view) on three different projects.
-
- Jack Carden The eye may see for the hand,
- Software Engineering but not for the mind.
- Carrollton, TX 75006 <Thoreau, 1849>
- Internet: carden@sdf.lonestar.org
-