pcg@aber-cs.UUCP (Piercarlo Grandi) (10/20/89)
Here are some coding "guidelines" for C++ programs. The approach is paranoid programming, wrt portability and language dark areas. Always put in an explicit storage class The rules for storage classes in C++ are fairly complex. You really want to always make explicit which storae class you want your data to be. Also, by starting every declaration with an explicit storage class, many ambiguities in the C++ grammar are avoided. This is both more readable and makes life easier for LR(1) parsers. Sure it is a pain to put auto or register in fron of every local variable, but readability improves a lot (to me, at least). Always prefix globals with ::, members with this->, static members with name:: Scope rules in C++ are somewhat more complex then in C. You want to look at an identifier and be positively sure from which scope it comes. All global identifiers should be prefixed with ::, and all members with this->; this avoids some very hard to catch bugs. Of course all class statics should be prefixed with name:: as well. Always put the data members first in a class A language rule allows you to put data members anywhere in a class, even after its first use in a member function. It is (as far as I can see) the *only* case where C++ does not allow one pass compilation. If you put all data members at the beginning, what is the data content of an object of a class is obvious to you and the compiler. If necessary, have two private:, protected: and public: sections, one each for data and procedure members. Always say whether a const is extern or static In C++ (not in Ansi C) consts have internal linkage by default (but not in some older versions of GNU C++, or some other compiler). Since it may well be that in the future (Ansi-C compatibility or whatever) the default may be changed, or you want your programs to be portable, always specify static or extern before const. There are some amusing issues here; what is compiler supposed to do with auto or register consts ? (the semantics are clear of course). You normally want your consts to be static, by the way. Always put class specific declarations inside a class scope This is easy only in C++ 2.0, where enums have scope local to the class where they appear, and static members are fully supported, both data and procedure ones. Otherwise, mangle the names yourself, and prefix the name of data and procedures associated with a class by the class name. By the way, too bad that it seems that in C++ 2.0 as well enums and consts defined in a class cannot be used in the same class, but are only visible after the class definition is completed. This prevents you from having array sizes defined in the class body... Always specify const in all places where it can be Now that const is available, const should be used as much as possible; this helps catching errors and optimizations. Use const also after *, and after the signature of a member function (new 2.0 feature) that does not modify the object. Sure putting const everywhere is verbose (especially because of the many "const type *const" cases), but useful... Note that in declarations of non pointer or reference parameters, specifying const is useless; e.g. the signature of sin can well be (double) instead of (const double), because the *user* of sin does not need to know whether the parameter is actually modified by the implementation of sin (because it is a copy of the argument); but when writing this implementation please do put in the const if the argument is not modified by it. Always have few, explicit inlines, outside the class definition, always static. Inline should be used sparingly, and mostly for one-liners; after all a C or C++ implementation should provide a fast procedure call protocol. Some compilers will respect the language definition and assume inline by default if the body of a procedure is conained within the class declaration, some will not. Don't take risks; *never* clutter up the body of class with procedure bodies, always put them outside it, always specify inline explicitly. Also, specify static explicitly with inline. This will be necessary under some compilers to prevent them from generating an offline procedure body, just in case there are external references (again, the default linkage for inline is not often respected). If you stick to the idea that inlines should be few and very small, you do not really want external linkage inlines anyhow. -- Piercarlo "Peter" Grandi | ARPA: pcg%cs.aber.ac.uk@nsfnet-relay.ac.uk Dept of CS, UCW Aberystwyth | UUCP: ...!mcvax!ukc!aber-cs!pcg Penglais, Aberystwyth SY23 3BZ, UK | INET: pcg@cs.aber.ac.uk
newsuser@lth.se (LTH network news server) (10/21/89)
In article <1148@aber-cs.UUCP> pcg@cs.aber.ac.uk (Piercarlo Grandi) writes: >Always prefix globals with ::, members with this->, static members with name:: > > All global identifiers should be prefixed with ::, and all > members with this->; this avoids some very hard to catch bugs. I haven't been bitten by this yet -- on the other hand, I try to write very simple programs. I would find all the "::" and "this->" to make the code less readable, hence more difficult to maintain. > Always put the data members first in a class I find the operations on a class (primarily the member functions) much more important than the actual data representation; I therefore put all member functions in front of the data members. In fact, I have many times wanted to hide the data members completely, which unfortunately is not possible without indirection. > If > necessary, have two private:, protected: and public: sections, one > each for data and procedure members. This is quite useful. I normally have the following order: 1. Public functions 2. Protected functions 3. Public data. 4. Protected data. 5. Private functions. 6. Private data. This discussion is of course much matter of taste -- your's or your manager's. Try different approaches! > Always specify const in all places where it can be. > Always have few, explicit inlines, outside the class definition, > always static. I think these are the most important of Piercarlo's rules. Dag Michael Bruck -- Department of Automatic Control Internet: dag@control.lth.se Lund Institute of Technology P. O. Box 118 Phone: +46 46-108779 S-221 00 Lund, SWEDEN Fax: +46 46-138118
bright@Data-IO.COM (Walter Bright) (10/24/89)
In article <1148@aber-cs.UUCP> pcg@cs.aber.ac.uk (Piercarlo Grandi) writes: < bad that it seems that in < C++ 2.0 as well enums and consts defined in a class cannot be used < in the same class, but are only visible after the class definition < is completed. This prevents you from having array sizes defined in the < class body... I thought I had a bug in Zortech 2.0 in that: class abc { enum def { A,B,C }; int func(enum def i = A); }; didn't work! (The default argument A wasn't recognized, because the class data structure was incomplete when the function declaration was parsed.) It's not clear from the 2.0 spec if this is expected to work. Is it?