6. Style
6.1. Classes
- Rule 20
- The public, protected, and private
sections of a class are to be declared in that order (the public section
is declared before the protected section which is declared before the
private section).
- Rule 21
- No member functions are to be defined
within the class definition.
By placing the public section first, everything that is of interest
to a user is gathered in the beginning of the class definition. The
protected section may be of interest to designers when considering
inheriting from the class. The private section contains details that
should have the least general interest.
A member function that is defined within a class definition
automatically becomes inline. Class definitions are less compact and more
difficult to read when they include definitions of member functions. It
is easier for an inline member function to become an ordinary member
function if the definition of the inline function is placed outside of
the class definition. This rule will be in effect at least as long as
traditional text editors are used.
A similar problem is that members are private if no access
specifier is explicitly given. This problem is avoided by following
Rule 20.
- Exception to Rule 20
- No exceptions.
- Exception to Rule 21
- No exceptions.
Example 15: A class definition in accordance with the style rules
class String : private Object
{
public:
String(); // Default constructor
String( const String& s ); // Copy constructor
unsigned length() const;
// ...
protected:
int checkIndex( unsigned index ) const;
// ...
private:
unsigned noOfChars;
// ...
};
Example 16: No definitions of member functions within the class definition (See Example 1)
// Instead of writing like this:
class String
{
public:
int length() const // No !!
{
return len;
}
// ...
private:
int len;
};
// Do it this way:
class String
{
public:
int length() const;
// ...
private:
int len;
};
inline
int
String::length() const
{
return len;
}
6.2. Functions
- Rec. 20
- Always provide the
return type of a function explicitly.
- Rec. 21
- When declaring functions, the
leading parenthesis and the first argument (if any) are to be written
on the same line as the function name. If space permits, other
arguments and the closing parenthesis may also be written on the same
line as the function name. Otherwise, each additional argument is to be
written on a separate line (with the closing parenthesis directly after
the last argument).
- Rec. 22
- In a function definition, the
return type of the function should be written on a separate
line directly above the function name.
- Rec. 23
- Always write the left parenthesis
directly after a function name.
If no return type is explicitly provided for a function, it is, by
default, an int. It is recommended to always provide the return type
explicitly, to increase the readability of the code. By defining the
return type on a separate line directly above the function definition,
the function name is more easily seen.
The other recommendations are meant to give a uniform appearance
to the code that is written. Until such time as formatting tools are
available, programmers should follow these guidelines.
Example 17: The left parenthesis always directly after the function name
void foo (); // No!!
void foo(); // Better
Example 18: Right and wrong ways of declaring formal arguments for a function (in function definition)
// Right:
int
myComplicatedFunction( unsigned unsignedValue,
int intValue,
char* charPointerValue,
int* intPointerValue,
myClass* myClassPointerValue,
unsigned* unsignedPointerValue );
// Wrong:
int
myComplicatedFunction( unsigned unsignedValue, int intValue,
char* charPointerValue, int* intPointerValue, myClass* myClassPointerValue,
unsigned* unsignedPointerValue );
6.3. Compound Statements
- Rec. 24
- Braces ("{}") which enclose a block
are to be placed in the same column, on separate lines directly before
and after the block.
The placement of braces seems to have been the subject of the greatest
debate concerning the appearance of both C and C++ code. We recommend
the style which, in our opinion, gives the most readable code. Other
styles may well provide more compact code.
6.4. Flow Control Statements
- Rec. 25
- The flow control primitives
if , else , while , for
and do should be followed by a block, even if it
is an empty block.
At times, everything that is to be done in a loop may be easily
written on one line in the loop statement itself. It may then be tempting
to conclude the statement with a semicolon at the end of the line. This
may lead to misunderstanding since, when reading the code, it is easy to
miss such a semicolon. It seems to be better, in such cases, to place
an empty block after the statement to make completely clear what the
code is doing.
Example 19: Flow control structure without statements
// No block at all - No!
while ( /* Something */ );
// Empty block - better!
while ( /* Something */ )
{
// Empty !
}
6.5. Pointers and References
- Rec. 26
- The dereference operator
'
* ' and the address-of operator '& ' should
be directly connected with the type names in declarations
and definitions.
The characters '* ' and '& ' should
be written together with the types of variables instead of with the
names of variables in order to emphasize that they are part of the type
definition. Instead of saying that *i is an int ,
say that i is an int* .
Traditionally, C recommendations indicate that '* '
should be written together with the variable name, since this reduces
the probability of making a mistake when declaring several variables
in the same declaration statement (the operator '* ' only
applies to the variable on which it operates). Since the declaration
of several variables in the same statement is not recommended, however,
such a advice is unneeded.
Example 20: * and & together with the type
char*
Object::asString()
{
// Something
};
char* userName = 0;
int sfBook = 42;int& anIntRef = sfBook;
Example 21: Declaration of several variables in the same statement
// NOT RECOMMENDED
char* i,j; // i is declared pointer to char, while j is declared char
6.6. Miscellaneous
- Rec. 27
- Do not use spaces around
'
. ' or '-> ', nor between unary operators
and operands.
- Rec. 28
- Use the c++ mode in GNU Emacs to
format code.
In our opinion, code is more readable if spaces are not used around
the . or -> operators. The same applies to unary operators (those that
operate on one operand), since a space may give the impression that the
unary operand is actually a binary operator.
Ordinary spaces should be used instead of tabs. Since different editors
treat tab characters differently, the work in perfecting a layout may
have been wasted if another editor is later used. Tab characters can be
removed using the UNIX command expand . One alternative is
to format code using the editor GNU Emacs.
We recommend that everyone use GNU Emacs to format code. Code will then have a uniform appearance regardless of who has written it.
|