[comp.lang.c++] Some "guidelines" for coding in C++

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?