Path: utzoo!attcan!uunet!wuarchive!cs.utexas.edu!rice!uupsi!sunic!news.funet.fi!funic!santra!fuug.fi!pena From: pena@fuug.fi (Olli-Matti Penttinen) Newsgroups: comp.lang.c++ Subject: Re: 1 Definition Allowed Message-ID: Date: 5 Nov 90 14:45:59 GMT References: <1990Oct30.125546.3702@kodak.kodak.com> <1463@proto.COM> <1990Nov1.202530.15347@cs.columbia.edu> <1990Nov5.051429.6109@sjsumcs.sjsu.edu> Sender: news@santra.uucp (Cnews - USENET news system) Organization: Finnish UNIX Users Group, Finland Lines: 74 In-Reply-To: horstman@sjsumcs.sjsu.edu's message of 5 Nov 90 05:14:29 GMT In article <1990Nov5.051429.6109@sjsumcs.sjsu.edu> horstman@sjsumcs.sjsu.edu (Cay Horstmann) writes: >What you cannot have (and that is STUPID) is multiple definitions of the >same struct in the same file. While it is perfectly legal to have fifteen >declarations of extern int x; or int foo(int);, and the compiler will >happily check for consistency, it is not legal to have two occurrences >of struct Complex { double re,im; }; in the same file. Quite the contrary. It would be a colossal waste of time to check the consistency of every type definition. Since the line must be drawn somewhere, I agree with ARM (and current C++ implementations) that the best place is right where it lies now: there has to be exactly one type definition per a user defined type per compilation unit. >I wish this were remedied. One of the best pieces of advice I know is >TO INCLUDE EACH HEADER FILE IN ITS OWN .C FILE, but it just doesn't work >for structs, enums, and typedefs. It does not appear too difficult to check. >I agree that checking consistency of inline functions is probably >unreasonable, and a redefinition error is reasonable there. By borrowing a bit of Modula-2 type of thinking, this problem can be elegantly alleviated: I suggest using an additional abstraction level, the module. Each module consists of a (small) number of types that are somehow logically connected (e.g. a collection and an accompanying iterator). The definitions of each type are placed in a single .h file, the interface to the module. A necessary evil is the need to put all public/protected inline definitions in this file, as well. Inline definitions should be apart from the class declaration body, however. For one thing, it's easier to find out what a class does, if it's declaration is uncluttered, on the other hand, potential forward reference problems can be handled this way. In a complex situation, another .h file might be handy: any constants, etc. that only affect the implementation and not the use of the module as well as bodies of private inline functions should be placed in it. Finally, definitions of member, static and global functions that implement the class, should be scattered across 1..n .C files, depending on their size and number. These would naturally include (in this order): system headers, interfaces of all modules used, the module's own interface and the private supplemental header file. Once compiled, the files could be combined to a library and shipped with the interface .h file. One problem remains: it would still be possible to accidentally include an interface more than once. This can be avoided if every interface "knows" whether it already is included or not: //interface.h #ifndef INTERFACE_H #define INTERFACE_H #include #include "anothermodule.h" class thisclass { . . . }; inline T thisclass::f() { ...}; #endif // EOF -- Olli-Matti Penttinen Brainware Oy "When in doubt, use brute force." Tekniikantie 17 --Ken Thompson 02150 ESPOO, Finland Tel. +358 0 4375 320 Fax. +358 0 4553 117