TITLE: Include file scheme PROBLEM: nh@cbnewsg.cb.att.com (nicholas.hounsome), 19 Nov 92 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. RESPONSE: carden@sdf.lonestar.org (Jack Carden), 10 Dec 92 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 #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. [ This scheme is interesting, but each file is still processed in its entirety twice. It would be optimal if there were a cpp directive like #stop (or something) which would force the preprocessor to quit processing the file. -adc ]