Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Path: utzoo!utgpu!water!watmath!clyde!cbosgd!ihnp4!drutx!druhi!weh From: weh@druhi.UUCP Newsgroups: comp.lang.c++ Subject: Re: Questions about C++ Message-ID: <2010@druhi.ATT.COM> Date: Fri, 10-Jul-87 12:02:46 EDT Article-I.D.: druhi.2010 Posted: Fri Jul 10 12:02:46 1987 Date-Received: Sun, 12-Jul-87 11:25:32 EDT References: <227@nih-csl.UUCP> <134@otc.OZ> <2002@druhi.ATT.COM> <229@nih-csl.UUCP> Distribution: comp Organization: AT&T, Denver, CO Lines: 119 Summary: can STILL use +e option with derived classes In article <229@nih-csl.UUCP>, keith@nih-csl.UUCP (keith gorlen) writes: > In article <2002@druhi.ATT.COM>, weh@druhi.ATT.COM (HopkinsWE) writes: > > A simple approach to using the +e option is to use +e0 (only include > > external reference to virtual table) for all .c files, and compile > > the .h files containing the class declarations using +e1 (generate > > globally accessible virtual tables). > > This won't work on my .h files -- I usually have derived classes. For > example, suppose you have a base class B with virtual functions > declared in the file B.h and classes D1 and D2 derived from B declared > in files D1.h and D2.h, respectively. Now to compile D1.h or D2.h, > you must include the declaration of their base class B, so you might > as well #include "B.h" in D1.h and D2.h. So if you compile both D1.h > and D2.h with the +e1 option both D1.o and D2.o have global > definitions of the vtbl for class B. Have I misunderstood something? Keith's observation is correct. The simplistic solution I suggested is fatally flawed; there is no point in using the +e option WITHOUT iheritance and virtual member functions. After some thought, writing a test case, and consultation with other C++ developers, a reasonable solution does exist. In summary, a special .c file is used to include ALL class declarations which needs a virtual table. That file is compiled using +e1 while all the other .c files are compiled using +e0. The following example illustrates this: // base.h #ifndef base_h #define base_h class base { int one_int; public: base () { one_int = 0; } virtual int get_one_int () { return one_int; } }; #endif // derived.h #ifndef derived_h #define derived_h #include#include "base.h" class derived: public base { int one_int; public: derived () { one_int = 1; } int get_one_int () { return one_int; } void display () { printf("derived::one_int = %d, base::one_int = %d\n", get_one_int (), base::get_one_int ()); } }; #endif // derived_2.h #ifndef derived_2_h #define derived_2_h #include #include "base.h" class derived_2: public base { int one_int; public: derived_2 () { one_int = 2; } int get_one_int () { return one_int; } void display () { printf("derived_2::one_int = %d, base::one_int = %d\n", get_one_int (), base::get_one_int ()); } }; #endif // defs.c #include "base.h" #include "derived.h" #include "derived_2.h" // main.c #include "derived.h" #include "derived_2.h" main() { derived one_obj; derived_2 one_obj_2; one_obj.display(); one_obj_2.display(); } This compiled using the following commands: CC +e1 -c defs.c CC +e0 main.c defs.o And executes with the expected results: $ a.out derived::one_int = 1, base::one_int = 0 derived_2::one_int = 2, base::one_int = 0 The #ifndefs are necessary to ensure that each class is included once (not a bad practice to follow in general). This approach has been used in some medium sized projects, and the problem experienced is that the preprocessor and compiler tables are stressed. Bill Hopkins AT&T 11900 N. Pecos St. Denver, CO 80234 {allegra|ihnp4}!druhi!weh