Appendix AC=2. C++ Language Coding Guidelines
AS2.1. Introduction
This coding style guide is a simplified version of one that has been used with good success both in industrial practice and for college courses. Of course, coding style preferences are intensely personal. However, having a uniform style within a group of programmers is enormously beneficial, and it can be achieved if every programmer is willing to compromise a little.
In these guidelines, we plainly outlaw a number of constructs. We don't mean to say that programmers using them are evil, merely that the constructs are of marginal utility and that better ways of expressing the same functionality exist in the language. Experience has shown that it is beneficial to stay away from marginal features. Programmers who don't know them need not make an effort to master them, and programmers who do need not make an effort to make a choice. We also demand consistency in naming and layout. These are of course trivial details, but reducing gratuitous choice in unimportant matters enables programmers to spend their energy on the solution of real problems.
We strongly recommend that programming teams and course instructors require adherence to this style guide, with suitable modifications for local taste, or one like it. Contact the author for a copy of this document in electronic form for modification and redistribution.
AS2.2. Modules
AU2.2.1. Module layout
Each C++ program is a collection of implementation files or modules. The executable program is obtained by compiling and linking its constituent modules.
Each module has certain public information, such as the declaration of public classes and functions that are implemented in it. It also has private information such as functions that are not called from outside, variables that cannot be inspected or modified from outside, and maybe local type declarations.
Unfortunately, C++ is not very supportive in this regard. All global data and functions are by default public. We require that you declare all functions and global data as static unless they are exported to other modules.
The public interface of a module is specified in a header file with the same name as the .cpp file but extension .h. It contains extern declarations of all exported global variables, prototypes of all exported functions and public type and class definitions.
Implementation and header files are organized as follows:
• Header comment block
• #include statements
• Constants
• Classes and type declarations
• Global constants and variables
• Functions
• Operations
• Test code
AU2.2.2. Header comment
Each module starts with a header comment block in the format below.
/*****************************************************************
COPYRIGHT (C):    1992, All Rights Reserved.
PROJECT:          CS 151 Project
FILE:             wm.c
PURPOSE:          widget manipulation
VERSION           1.0
LANGUAGE:         Borland C++ 3.1
TARGET:           IBM PC
PROGRAMMER:       Cay Horstmann (CSH)
J                  enny Koo (JK)
UPDATE HISTORY:
*****************************************************************/

/* GENERAL *******************************************************

General comments go here, for example:
- command line options
- file formats
- rules and conventions
- pictures of the main data structures
...
*****************************************************************/
AU2.2.3. Included header files
The next section lists all included header files.
/* INCLUDE ******************************************************/

#include <stdlib.h>
#inlcude <string.h>
#include "cw.h"
#include "..\util\keys.h"
#include "wm.h"
Sort header files in the order shown:
• system header files <xxx.h>
• local header files "xxx.h"
• the module's own header file
Follow the convention of using <...> for the files stored in the ”standard place“ of the compiler (e.g. \borlandc\include), "..." for the files stored in the local directory. Do not embed absolute path names, e.g
#include <c:\borlandc\include\stdlib.h> // DON'T !!!
AU2.2.4. The class section
This section contains the definitions of classes, enumerations, and types, in any order.
/* CLASSES ******************************************************/

enum Weekday { MON, TUE, WED, THU, FRI, SAT, SUN };

typedef int (*DateCompareFun)(Date, Date);

class Date
/* PURPOSE: Store dates and perform date arithmetic
*/
{
public:
// ...
};

AU2.2.5. The globals section
Then come the definitions of global constants and variables. All global variables that are not declared in the header file must be declared as static, i.e. private to the module.
We strongly caution the programmer against using global variables. In our experience, having more than three global variables in a module is excessive.
/* GLOBALS ******************************************************/

static const int days_per_month[] = { 31, 28, 31, 30, ... };
// the number of days in every month (except for leap years)

const int JULYEAR0 = -4713;
// Julian day 0 = Jan. 1, -4713
AU2.2.6. The functions section
This section lists all functions of the module. First, list prototypes (if any), then the functions. All functions without a prototype in the header file must be declared static, i.e. private to the module.
You may sort the functions in any order, but we recommend that you sort them in reverse order of call. In particular, the module containing main has main last. If you follow this layout, you never need prototypes, except in the rare case of a cyclic calling pattern among the static functions.
We list the functions before the operations of classes because the operations need to know about the static functions, whereas the functions already know the operations from the class definitions.
In an object-oriented program, it would be surprising to see more than a handful of functions per module.
/* FUNCTIONS ****************************************************/

static long dat2jul(int d, int m, int y)
/* PURPOSE: Convert calendar date into Julian day
RECEIVES: d, m, y - the day, month and year
RETURNS: The Julian day number that begins at noon of the given calendar date.
REMARKS: This algorithm is from Press et al., Numerical Recipes in C, 2nd ed., Cambridge University Press 1992
*/
{ // ...
}

/*--------------------------------------------------------------*/

istream& operator>>(istream& is, Date& date)
/* PURPOSE: Read a date from a stream
RECEIVES: is - the stream
d (OUT) - the date that is read in
RETURNS: is
*/
{ // ...
}

/*--------------------------------------------------------------*/

int main(int argc, char* argv[])
{ // ...
}

U2.2.7. The operations section
This section lists all operations of classes. Sort them by class. Separate operations of the same class by /*......*/, member functions of different classes by /*------*/ comment lines.
/* OPERATIONS ***************************************************/

Date::Date(int d, int m, int y)
/* RECEIVES: d, m, y - the day, month and year
*/
:  _day(d),
_month(m),
_year(y)
{}

/*..............................................................*/

long Date::days_between(Date b) const
/* RECEIVES: b - a date
RETURNS: The number of days between this date and b
*/
{  // ...
}
U2.2.8. The test section
This section is optional but highly recommended. It contains a test stub to test the classes and operations implemented in the module. The test stub is enclosed in preprocessor directives for conditional compilation. It is only compiled when testing the module.
/* TEST *********************************************************/

#ifdef TEST_DATE

#include <stdlib.h>
#include <iomanip.h>

int main(int argc, char* argv[])
/* RECEIVES: month year
*/
{ int m = atoi(argv[1]);
int y = atoi(argv[2]);
Date d(1, m, y); // start date of the month

cout << "Mon Tue Wed Thu Fri Sat Sun" << endl;
Weekday w = d.weekday();
for (int i = 0; i < w; i++) cout << "    ";
while (d.month() == m)
{  cout << setw(4) << d.day();
if (d.weekday() == SUN) cout << endl;
d.advance(1);
}
if (d.weekday() != MON) cout << endl;
return 0;
}

#endif
AS2.3. Classes
AU2.3.1. Class header comment
Each class declaration starts with a header comment.
class name [ : public base class [ , public base class ] *  ]
/* PURPOSE:
STATES:
*/
{ // ...
};

The PURPOSE comment is mandatory. Describe the class in some way. You may phrase the description for an object of the class: ”A mailbox stores and plays mail messages“.
The STATES comment is very useful in understanding those classes that have clearly defined states that influence their behavior.  For example, a bounded stack has two special states ”empty“ and ”full“ that change the way that pop and push behave. Omitting the STATES comment implies that the class has no states that are observable through the public interface.
AU2.3.2. Base classes
We only use public inheritance.
Use aggregation instead of private inheritance, that is, replace
class C : private B {}
with
class C { private: B _b; }
This requires no change in the interface of C.
There is protected inheritance, but we don't allow it.
AU2.3.3. Class layout
First list the public section, then the private section. (If you have a protected section, put it in between the two. We disallow protected data and are neutral on protected operations.)
Within each section, order features as follows:
• Local classes, enumerations, and types
• Constructors (except copy constructor)
• Mutators: non-const operations
• Accessors: const operations functions
• static and friend functions
• Memory management: Copy constructor, destructor, operator=
• data fields
• static (shared) class variables
This order is partially psychological, partially pragmatic. For the reader of a class, the public interface is the most important aspect and therefore must come first. The private section may change and should be of no great concern to most class users. In each section, we order items to answer the following questions:
• How can I make an object? (constructors)
• Then, what can I do to it? (mutators)
• Then, how can I find out what I did? (accessors)
We need to place the local types before these items because some of them may refer to them. And we place memory management functions (copy constructor, destructor, assignment operator) at the end because they are uninteresting for the class user. (N.B. Do not supply these functions unless the default ones supplied by the compiler are inadequate.)
Each public feature and each data field that is not totally obvious from its name should have a one-line comment. You can omit comments for patently obvious functions like print(). More detailed descriptions will be found in the operations section.
class String
/* PURPOSE: character strings
*/
{
public:
enum {NPOS = INT_MAX};
// maximum number of positions in string

String(); // constructs an empty string
String(const char s[]);
String(char ch);

char& operator[](int i);
void set(int i, char ch); // change a character
// ...

int length() const;
Bool is_null() const;
char get(int i) const; // get a character
String substr(int from, int n = NPOS) const;
String operator+(const String&) const; // concatenate

friend String operator+(const char a[], const String& b);
static compare(const String&, const String&);

String(const String&);
const String& operator=(const String&);
~String();

private:
String(size_t len, const char s[], size_t slen);

void detach();
void unique();

char* _str;
};
AU2.3.4. Friends
The C++ compiler does not care where friend declarations are placed inside a class definition. We follow this rule:
A friend function that is used by the public is placed at the end of the public section. A friend declaration that serves for the implementation of the class is placed at the end of the private section. For example,
class List
{
public:
// ...
friend ostream& operator<<(ostream&, const List&);
private:
Link* _head;
friend class Iterator;
};
U2.3.5. Operations
In the declaration, do not omit the argument names of member functions, e.g. don't use
class String
{
public:
String remove(int, int); // NO
// ...
};
Which int does what?
Do not use inlines in class declarations.
class Polygon
{
public:
void set(int n, Point x) { _vertex.set(n, x); } // NO
// ...
};
Instead, use
class Polygon
{
public:
void set(int n, Point x) { _vertex.set(n, x); } // NO
// ...
};

inline void Polygon::set(int n, Point x)
/* PURPOSE: set a vertex of a polygon
RECEIVES: n - position of vertex
p - vertex
*/
{ _vertex.set(n, x);
}
Sure, it is torture to type all this for a trivial function. (They don't call it ”strong typing“ for nothing...) But there are a number of benefits. It is much easier to revoke the inline attribute. The inline source code doesn't clutter up the public interface. There is room for a decent comment for those functions that require it. For example, the operation above would benefit from an explanation on the behavior if n is larger than the number of vertices of the polygon.
The only exception to this rule is that we permit do-nothing inlines for default constructors and virtual destructors in the class definition.
class Customer
{
public:
Customer() {};
// ...
virtual ~Customer() {}
};
AU2.3.6. Data fields
In a class, all data fields must be private. Prefix each field name with an underscore (_age).
Use accessor and mutator functions to access and change the data.
class Employee
{
public:
int age() const;
void set_age( int a ) ;
// ...
private:
int _age;
// ...
};
Use the naming scheme _field, field(), set_field() consistently. (Actually, it is not entirely clear why one would want to set the age of an employee. It would make more sense to store the birthday and compute the age. This kind of design change is of course the reason for insisting on private data.)
AS2.4. Operations and functions
U2.4.1. Header comment
Each operation and function has a comment of the following form.
/* PURPOSE: explanation
RECEIVES:  argument 1 - explanation
argument 2 - explanation
...
RETURNS: explanation of return value
REMARKS: pre- and postconditions, exceptions, etc.
*/
The PURPOSE comment is required, except for constructors, destructors, assignment operators, field accessors and very trivial functions that are adequately described by their return value. The RECEIVES comment is omitted if the function takes no arguments. The RETURNS comment is omitted for void functions.
No purpose and return value comments are necessary for main. Explain the command line arguments in the RECEIVES section.
static long dat2jul(int d, int m, int y)
/* PURPOSE: Convert calendar date into Julian day
RECEIVES: d, m, y - the day, month and year
RETURNS: The Julian day number that begins at noon of the given calendar date.
REMARKS: This algorithm is from Press et al., Numerical Recipes in C, 2nd ed., Cambridge University Press 1992
*/
{ // ...
}

Reference arguments that have no well-defined incoming value but are used to hold a result must be tagged as OUT.
istream& operator>>(istream& is, Date& date)
/* PURPOSE: Read a date from a stream
RECEIVES: is - the stream
d (OUT) - the date that is read in
RETURNS: is
*/
{ // ...
}
AU2.4.2. Declaration attributes
Every function must have a return type. Use void for procedures.
Every accessor operation must be declared as const.
Every global function must be declared static unless its declaration is exported to the header file.
AU2.4.3. Parameters
Parameter names should be explicit, especially if they are integers or Boolean.
Customer Bank::remove(int i, Bool b); // huh?
Customer Bank::remove(int teller, Bool display); // OK
Of course, for very generic functions, short names may be very appropriate.
For each array, pointer or reference argument, use const if the argument is not modified by the function. The function is presumed to modify all non- const pointer, reference and C array arguments.
void Mailbox::add(Message& m); // will modify m
void Mailbox::add(const Message& m); // won't modify m
Never use pointers to denote C arrays. Pointer parameters are presumed to point to a single object.
void find(const Employee* e, int idnum);
// e points to a single object (maybe derived from Employee)
void find(const Employee e[], int idnum);
// e is a C array of objects (of exact type Employee)
Do not use pointers for reference arguments. Use references instead.
void swap(int* px, int* py); // NO
void swap(int& px, int& py); // OK
Do not use pointers to avoid the cost of call by value. If
int Bank::find(Customer c);
is considered too inefficient, use a constant reference instead.
int Bank::find(const Customer& c);
Of course, if all objects of the type are located on the heap, and you always access them with pointers, then a pointer parameter is ok. We only object to taking the address of a stack object in the call.
Do not write procedures (void functions) that return exactly one answer through a pointer or reference. Instead, make it into a return value.
void Bank::find(Customer c, Bool& found); // NO!
Bool Bank::find(Customer c); // OK
Of course, if the function computes more than one value, some must be returned through reference arguments.
AU2.4.4. Function length
As a rule of thumb, functions should not be longer than 30 lines of code. The function header, comments, blank lines and lines containing only braces are not included in this count. For operations of classes, this limitation is rarely a problem. Functions that parse input with a long switch statement or if/else may end up being much longer, but then keep each branch to 10 lines or less.
AU2.4.5. Constructors
It is considered good style to write constructors so that all data members are constructed outside the {...} and only non-trivial actions are placed inside. For example,
Date::Date(int d, int m, int y)
/* RECEIVES: d, m, y - the day, month and year
*/
:  _day(d),
_month(m),
_year(y)
{ assert_precond(valid());
}
AS2.5. Variables
AU2.5.1. Comments
Every local variable, with the exception of really self-explanatory names and boring loop counters, must be commented when declared. Every global variable must be commented, without exception.
int nfont = 0; // the number of fonts currently loaded
AU2.5.2. Initialization
Every variable must be explicitly initialized whenever possible.
int nfont = ft_load();; // the number of fonts currently loaded
It is almost always possible to do this in C++, by declaring the variable just before it is to be used for the first time. Remember that variable declarations and statements can be freely mixed.
Move variables to the innermost block in which they are needed.
while( /* ... */ )
{ int b = f();
// ...
}
This is considered good style, much better than declaring all variables at the beginning of the function.
AU2.5.3. Pointers
We recommend the C++ convention of placing the * with the type, not the variable, e.g.
Shape* p;
not
Shape *p;
Of course, the compiler doesn't care. It ignores all white space, and we could equally well have written
Shape*p;
or
Shape
*
p
;
It seems to be more rational to declare p as a Shape* rather than declaring p as a thing whose * is a Shape.
You cannot declare two pointers like that:
Shape* p, q;
This declares a pointer p and an integer q. Don't declare two pointers in the same line, write
Shape* p;
Shape* q;
instead. Since you will need to write comments behind the declarations, this should never be a problem.
It is traditional, but extremely silly, to write the const for constant pointers and references as far as possible from the * or & to which they apply.
const Shape* s;
We encourage you to use
Shape const* s;
If more than one pointer or reference is required, that is the only way to preserve your sanity. A constant reference to a pointer (say for a hash function in a template) is
int hash(Employee* const&),
a reference to a constant pointer (say for a read function) is
void archive(Employee const*&).
AU2.5.4. Global variables
Global variables are those declared outside functions. When declared as static, they can be read and modified by all functions in the current module (hundreds of lines of code). When exported, they can be read and modified by all functions in the program (many thousands of lines of code). This is unreasonable in practice.
There is a simple strategy for minimizing global variables: Group related variables into classes.
Don't use
int win_top, win_left, win_bot, win_right, cur_row, cur_col;
Instead, use
class Window
{ // ...
private:
int win_top, win_left, win_bot, win_right;
int cur_row, cur_col;
};

Window display_win;
A prime candidate for grouping are arrays of the same length. Don't use
int charwidth[NCHAR];
char* pixels[NCHAR];
unsigned char charcode[NCHAR];
Instead, use
class BitmapChar
{ // ...
private:
int _width;
char* _pixels;
unsigned char _code;
};

BitmapChar display_font[FT_NCHAR];
In fact, it makes sense to go one step further and declare a type BitmapFont.
class BitmapFont
{ // ...
private:
String _name;
Array<BitmapChar> _characters;
};

BitmapFont display_font;
In C++, it is often possible to replace global variables by shared class variables.
class Date
{ // ...
private:
int _day, _month, _year;

static const int _days_per_month[12];
};

const int Date::_days_per_month[12] = { 31, 28, ..., 31 };
This is considered good programming practice.
AS2.6. Constants
AU2.6.1. Constant definitions
In C++, do not use #define to define constants.
#define NFONT 20
// DON'T
Use const instead.
const int FT_NFONT = 20; // the maximum number of fonts
AU2.6.2. Zero
Should you use '\0' and NULL, or just plain 0? We leave this to you. It makes sense to use the ”strongly typed“ explicit symbols instead of 0. On the other hand, it is well within the spirit of C++ to use 0 as an overloaded symbol to denote the ”right“ zero value in various contexts.
AU2.6.3. Enumerations
Use enum to define a number of related constants.
enum Color { BLUE = 1, GREEN = 2, RED = 4 };
Do not use a sequence of const or #define!
Avoid global enumerations. Whenever possible, make enumerations local to a class.
class Date
{
public:
enum Weekday { SUN, MON, TUE, WED, THU, FRI, SAT };
// ...
private:
// ...
};
The programmer refers to these constants as Date::SUN, Date::MON etc. The names SUN, MON etc. don't clutter up the global name space. That avoids nasty conflicts with other enumerations.
enum Workstation { SUN, DEC, HP, IBM, };
enum Exam { SAT, GRE, GMAT, };
When defining an open-ended number of enums, place a comma behind the last one:
enum Tokentype
{ NIL,
// ...
FRACTION,
ROOT,
MATRIX,
TABLE,
};
It is legal, and it makes it easier to add another one.
It is often useful to have the compiler keep track of the total number of items:
enum Tokentype
{ NIL,
// ...
FRACTION,
ROOT,
MATRIX,
TABLE,
// add new token types above this line
TK_NTOKENTYPE
};
Now NTOKENTYPE keeps track of the number of token types defined. Be sure to include the comment, directing the person maintaining the code to insert new types before the counter.
In C++, it is common to use enum to define constants used inside classes. For example,
class Stack
{ // ...
private:
enum { SSIZE = 20, }
int _item[SSIZE];
int _stackptr;
//...
};
The seemingly more rational
class Stack
{ // ...
private:
const int SSIZE = 20; // NO!
int _item[SSIZE];
int _stackptr;
//...
};
is a syntax error.
AU2.6.4. Magic Numbers
A magic number is a integer constant embedded in code, without a constant definition. Using magic numbers makes code amazingly difficult to maintain. They are strictly outlawed.
Even the most reasonable cosmic constant is going to change one day. You think there are 365 days per year? Your customers on Mars are going to be pretty unhappy about your silly prejudice. Make a constant
const int DAYS_PER_YEAR = 365
so you can easily cut a Martian version without trying to find all the 365's, 364's, 366's, 367's etc... in your code. By the way, the device
const int THREE_HUNDRED_AND_SIXTY_FIVE = 365
is counterproductive and frowned upon.
You can take it for granted that all array lengths will change at least twice (oops, meant to say, at least N_BUFLEN_CHANGE times) during the lifetime of the code. Declare the length of each fixed size array as an individual constant. Don't use the same constant for two arrays unless for compelling logical reasons the two arrays have to have the same length.
AS2.7. Control flow
AU2.7.1. The if statement
Avoid the ”if...if...else“ trap. The code
if( ... )
if( ... ) ...;
else
{ ...;
...;
}
will not do what the indentation level suggests, and it can take hours to find such a bug. Always use an extra pair of {...} when dealing with ”if...if...else“:
if( ... )
{ if( ... ) ...;
else( ... ) ...;
} // {...} not necessary but they keep you out of trouble

if( ... )
{ if( ... ) ...;
} // {...} are necessary
else ...;
AU2.7.2. The for statement
Do not the for loop for weird constructs (even though [Kernighan & Ritchie] contains an occasional abuse.) Constructs such as
for (r = i = 0; s[i]; r += s[i++] - '0') r *= 10;
are not tolerated. Make it into a while loop. That way, the sequence of instructions is much clearer.
r = i = 0;
while (s[i])
{ r *= 10;
r += s[ i++ ] - '0';
}
Only use for loops when a variable runs from somewhere to somewhere with some constant increment/decrement.
for (i = a.low(); i <= a.high(); i++)
a[i].print();
A for loop traversing a linked list can be neat and intuitive:
for (l.reset(); !l.at_end(); l.next())
l.current().print();
AU2.7.3. The switch statement
The switch statement should be laid out as follows:

switch (x)
{ case a:
...
...
break;
case b:
...;
return;
case c:
case d:
case e:
...;
...;
break;
default:
...;
...;
break;
}
Every branch must end in a break or return statement, even the last one. ”Fall through“ is not permitted. You don't have to use a default, but if you do, put it at the end of the switch.
AU2.7.4. Nonlinear control flow
Do not use the break (except in switch), continue and goto statements under any circumstances.
It is always possible to avoid a break in a loop by adding another Boolean variable. It makes for a clearer loop because you can easily verify the loop invariant.
The loop
for (i = a.low(); i <= a.high(); i++)
if(a[i] == x) // found it
break; // DON'T!
if (i > a.high()) // never found
...
can easily be rewritten as
Bool found = FALSE;
i = a.low();
while (!found && i <= a.high())
{ if( a[i] == x ) found = TRUE;
else i++;
}
if (!found)
...
The break and continue commands are not stable. Adding more loops or statements at the end of a loop change their meaning. goto is for yacc output, not for code produced by humans.
The only nonlinear control flow statements that you may use are return and throw.
AS2.8. Lexical issues
AU2.8.1. Naming convention
The following rules specify when to use upper- and lowercase letters in identifier names.
(1) All variable and function names and all structure members are in lowercase (maybe with an occasional upperCase letter or under_score in the middle). For example, font_cache.

(2) All #defined constants and macros, all enum constants and all inline const are in uppercase (maybe with an occasional UNDER_SCORE). For example, CACHE_SIZE.

(3) All typedefs and all C++ struct, class, union, enum names start with uppercase and are followed by lowercase (maybe with an occasional UpperCase letter or Under_score.) For example, FontCache.
Names should be explicit. Names should be reasonably long and descriptive. Use font_pointer instead of fp. No drppng f vwls. Local variables that are fairly routine can be short (ch, i) as long as they are really just boring holders for an input character, a loop counter etc... And, do not use ptr, p, pntr, pnt, p2 for five pointer variables in your function. Surely these variables all have a specific purpose and can be named to remind the reader of it (e.g. pcur, pnext, pprev, pnew, pret...).
AU2.8.2. Indentation and white space

Use tab stops every 3 columns. The default of 8 columns wastes screen real estate.

Use blank lines freely to separate logically separate parts of a function.

Separate functions by comments like /*---------*/.

Use a blank space around every binary operator and ?:.

ch = i < IO_BUF_SIZE ? curChar : 0; /* GOOD */
ch=i<IO_BUF_SIZE?curChar:0;/*BAD*/
Leave a blank spaces after (and not before) each comma, semicolon, and keyword, but not after a function name.
if (x == 0)
f(a, b[i++]);
Every line must fit on 80 columns. If you must break a statement, add an indentation level for the continuation:
a[n] = ..................................................
+ .................;
Start the indented line with an operator (if possible).
If this happens in an ”if“ or ”while“, be sure to brace in the next statement, even if there is only one.
if( .........................................................
&& ..................
|| .......... )
{    ...
}
If it wasn't for the braces, it would be hard to visually separate the continuation of the condition from the statement to be executed.
AU2.8.3. Braces
Opening and closing braces must line up, either horizontally or vertically.
while (i < n) { a[i].print(cout); i++; }

while (i < n)
{ a[i].print(cout);
i++;
}
Some programmers dont line up vertical braces but place the { behind the while, arguing that it saves a line of code.
while (i < n) { // DON'T
a [i].print(cout);
i++;
}
Huh? Counting the lines above does not seem to support that theory.
When the braces line up, it is easy to spot mismatches.
AU2.8.4. Unstable layout
Some programmers take great pride in lining up the names of class features.
class Date
{
public:
		Date(int d, int m, int y);	
	long	 days_between(Date b);	
	Weekday	 weekday() const;	
		// ...	

private:
	int	 _day;		
	int	 _month;		
	int	 _year;		

};
This is undeniably neat, and we recommend it if your editor does it for you. But don't do it manually on programmer's wages. The layout is not stable under change. A return type that is longer than the preallotted number of columns requires that you move all entries around.
Some programmers like to format multiline comments so that every line starts with **.
/* This is a comment
** that extends over
** three source lines
*/
Again, this is neat and a good thing if your editor has a command to add and remove the asterisks. Otherwise, it is a silly thing to do since it is a powerful method of discouraging programmers from editing the comment. If you have to choose between pretty comments and comments that reflect the current facts of the program, facts win over beauty.
AU2.8.5. The preprocessor
It has been said that all usage of the preprocessor points to deficiencies in the programming language. C++ fixes some deficiencies. Do not use #define for constants or macros––use const, enum and inline instead.
Do not use the #define facility to aid your transition from Pascal, like
#define begin {
#define end   }
#define repeat        do {
#define until( x )    } while( !( x ) );
Neat as they may be, these constructs are strictly outlawed. Your fellow programmers have better things to do than play preprocessor with your code.
A legitimate use for the preprocessor is conditional compilation (e.g. #ifdef WIN31 ... #endif).
To comment out a block of code that may itself contain comments, use #if 0 ... #endif. (Recall that C++ comments do not nest.)