Anda di halaman 1dari 12

C++ CODING STANDARDS

GlobalSCAPE, Inc.
Last Update: 09 June 2000 (GTH)
Table of Contents
TABLE OF CONTENTS ......................................................................................................................... 1
INTRODUCTION..................................................................................................................................... 1
SOURCE FILES ....................................................................................................................................... 1
STRUCTURE AND NAMING CONVENTIONS ................................................................................................ 1
FILE NAMING ........................................................................................................................................... 1
COMMENTS............................................................................................................................................. 2
FILE COMMENTS ...................................................................................................................................... 2
CLASS, METHOD, AND FUNCTION COMMENTS ........................................................................................ 3
INCLUDE FILES...................................................................................................................................... 5
ASSIGNING NAMES............................................................................................................................... 6
STYLE ....................................................................................................................................................... 7
CLASSES .................................................................................................................................................. 7
FUNCTIONS .............................................................................................................................................. 7
COMPOUND STATEMENTS ........................................................................................................................ 8
FLOW CONTROL STRUCTURES ................................................................................................................. 8
QUALITY FACTORS.............................................................................................................................. 8
DEBUGGING ............................................................................................................................................. 8
CODE COMPLEXITY.................................................................................................................................. 9
CODING PRACTICES ............................................................................................................................ 1
REFERENCES.......................................................................................................................................... 2
Introduction
This document represents the coding standards established at GlobalSCAPE, Inc. Standardization of
coding practices yields higher productivity through increased understanding, better organization, and
higher re-use potential of source code. It is not the intent of coding standardization to inhibit
programmer creativity; rather, coding is standardized only to the extent that the creativity and
production of a programmer is done in an organized, logical, understandable, and repeatable manner.
In short, any software developed at GlobalSCAPE, Inc. should be
• Correct
• Easy to Maintain
In order to achieve these goals, the source that produces the software should:
• Have a consistent style,
• Be easy to read and understand,
• Be free of common type errors,
• Be maintainable by different programmers,
• (Be portable on other architectures)
Refer to the section entitled References at the end of this document for a collection of excellent material
discussing guidelines for programming in C / C++.
This document is based heavily on the coding standards recommended by the Ellemtel-rules found in the
references.

Source Files

Structure and Naming Conventions

Rule 1 Include files always have the file name extension “.h”

Rule 2 Implementation files always have the file name extension “.cpp”

The purpose of these conventions is to provide a uniform interpretation of file names.


There are two kinds of files generally accepted by C++ compilers: those which contain code that is
accepted by both ANSI-C and C++ compilers and those which contain code that is only accepted by
C++ compilers. It is appropriate to distinguish between the two in order to avoid misunderstanding as
well as unpleasant compilation errors.

Exceptions Implementation files which contain code that is written specifically to


to Rule 2: ANSI C standards should have the file name extension “.c”

File Naming
Always give a file name that is descriptive and unique for the entire project.
Rule 3 Use the same capitalization techniques used in source code for file names.
Comments

It is imperative for understanding source code that it be well documented. Proper choice of variable
names, method names, class names, etc. provides for self documenting code and reduces the need for
comments within the code.

File Comments
File comments are placed at the beginning of each source file in order to describe, in a high level
fashion, the purpose of the file as well as to track any modifications / revisions made to the file.

Every file that contains source code must be documented with an


introductory comment block that provides information on the contents,
Rule 4 purpose, creation date, etc. See below for comment template and example.

Rule 5 All files must include copyright information

Rule 6 All comments are to be written in English


All documentation comments described in this section are to use the //
comment marker. /* */ comment markers are reserved for testing and
Rule 7 debugging. In other words, documentation in the form of comments shall
always use the // markers; the /* */ markers shall be used exclusively for
disabling code fragments during development.

The format for a file header comment is shown below.


//
// File: File Name here
// Description: descibe role or purpose of this file
// Created: date of file creation
// Author: Your_Name(s)
// with assistance from:
//
// Creation Date: Creation_Date
// modified: Modification_Date reason (one for each modification)
//
// Copyright (c) 2000 GlobalSCAPE, Inc.
// The copyright to the computer program(s) herein
// is the property of GlobalSCAPE, Inc.
// The program(s) may be used and/or copied only with
// the written permission of GlobalSCAPE, Inc.
// or in accordance with the terms and conditions
// stipulated in the agreement/contract under which
// the program(s) have been supplied.
//
Example 1: File Header comment
//
// File: foo.cpp
// Description: This is a test program that foos really well
// Author: Gregory T. Hoffer
// Created: 09 June 2000
//
// Copyright (c) 2000 GlobalSCAPE, Inc.
// The copyright to the computer program(s) herein
// is the property of GlobalSCAPE, Inc.
// The program(s) may be used and/or copied only with
// the written permission of GlobalSCAPE, Inc.
// or in accordance with the terms and conditions
// stipulated in the agreement/contract under which
// the program(s) have been supplied.
//

Class, Method, and Function Comments


Source code comments are often said to be either “tactical” or “strategic”. A strategic comment
describes what a function or section of code is intended to do, and is placed before this code. A tactical
comment describes what a single line of code is intended to do, and is placed, if possible, at the end of
this line. Unfortunately, too many tactical comments can make code unreadable. For this reason, it is
recommended to primarily use strategic comments, unless trying to explain very complicated code.
The standardization of comments makes it possible to automatically generate external documentation
(help files, man pages, etc.) from source code. This may be used to keep source code and documentation
together until adequate tools for information management are available
If the characters // are consistently used for writing comments, then the combination /* */ may be used
to make comments out of entire sections of code during the development and debugging phases. C++,
however, does not allow comments to be nested using /* */

Every Class declaration must be documented with an introductory comment


Rule 8 block. See below for template and example.
Every Method and free function definition must be documented with an
Rule 9 introductory comment block. See below for template and example.
Every block of code that is highly complex or particularly difficult to
Rule 10 understand must be preceded with inline comments that describe the
purpose and mechanism of that code.
Note: The Visual C++ Intellisense feature provides an option to display comments that are included with a function (refer
to http://msdn.microsoft.com/library/devprods/vs6/visualc/vcug/vchowviewingcodecomments.htm). It is recommended
that any function that requires special handling have comments added at the end of the declaration of that method.
The format for a class header comment is shown below.
// CLASS DECLARATION
// NAME: the name of this class
// AUTHOR: author’s name
// CREATED: creation date
// MODIFIED: any modifications include date and mod notes here
// PURPOSE: brief description of the purpose of this class
// LIMITATIONS: any known limitations for this class
// TESTING NOTES: name and descriptions of any test stubs, drivers, conditionals
// defines, etc. that can be used to test this class
// REUSE NOTES: note any potential reuse for this class, including any mods that
// might have to be made to generalize the functionality
Example 2: Class Declaration comment
// CLASS DECLARATION
// NAME: CFooBar
// AUTHOR: Gregory T. Hoffer
// CREATED: 09 June 2000
// PURPOSE: this class acts as the controller for a CBar object, using the
// Model/View/Controller design patter. The CBar is the model, CFoo
// is the view
// LIMITATIONS: tightly coupled with CBar and CFoo; consider revising
// TESTING NOTES: be sure to test dynamic creation of CFooBar in multithreaded app
// REUSE NOTES: this could serve as the basis for a specialized M/V/C component
//

The format for a method or free function definition is given below


// SUMMARY [CL x] where x is confidence level, 0-100%, of this method/function
// NAME: the name of this function/method
// AUTHOR: author’s name
// PARAMS: include parameters and their purpose
// RETURNS: type and purpose of return value from function
// CREATED: creation date
// MODIFIED: any modifications include date and mod notes here
// PURPOSE: brief description of the purpose of this class
// NOTES: general notes on the function/method
// CODE WALKTHROUGH: Individual initials and date of person doing initial code
// walkthrough (see quality factors section below)
// UNIT TESTED: individual initials and date of person doing unit testing

Example 3: Method/Function definition comment


// SUMMARY [CL 25]
// NAME: CFooBar::doSomething
// AUTHOR: Greg Hoffer
// PARAMS: int iObjectID -- the id of currently selected item in model
// struct action_type atAction -- what action to perform on object
// RETURNS: boolean -- TRUE if successful, FALSE otherwise
// CREATED: 09 June 2000
// PURPOSE: perform the requested action on the item currently selected in CBar
// NOTES:
// CODE WALKTHROUGH: 09 June 2000 RWE
// UNIT TESTED:

// don’t use this in Win95/98!!! [ this will show up in intellisense ]


boolean CFooBar::doSomething( int iObjectID,
struct action_type atAction )
{
. . .
}

Example 4 Strategic and Tactical Comments


// THE NEXT TWO LINES ARE STRATEGIC COMMENTS
// This function does some complicated things. It works like this:
// blah-blah-blah ...
int
InsanelyGreatAndComplicatedFunction( int i )
{
int Index = i++ + ++i * i-- - --i; // THIS IS A TACTICAL COMMENT

return Index;
}
Include Files

Every Include file must contain a mechanism to prevent multiple inclusions


Rule 11 of that file.
When any of the following kinds of definitions are used (in implementation
or other include files), they must be included as separate include files:
• classes that are used as base classes
• classes that are used as member variables
Rule 12
• classes that appear as return types or as argument types in
function/member function prototypes
• function prototypes for functions/member functions used in inline member
functions that are defined in the file

Rule 13 Never specify relative pathnames in #include directives

The easiest way to avoid multiple includes of files is by using an #ifndef/#define block in the beginning
of the file and an #endif at the end of the file
True portable code is independent of the underlying operating system. For this reason, relative search
paths should be avoided when including files. The processing of such search paths depends on the
compiler and platform. Instead, search paths should be provided in `make' files as options for the
compiler (which is equivalent to including them in the project workspace settings in Visual C++).
Inner classes can be used to declare classes that are member variables of
another class ONLY under highly specialized situations in which industry
Exceptions accepted and proven practices warrant their use. Due to potential reduced
to Rule 12: reusability and possible misunderstanding of purpose, this practice should
be avoided in the majority of situations.

Examples of situations that might warrant inner classes would be iterators and aggregating com
interfaces to implement inner and outer objects.
Every C++ course teaches the difference between the include directives for user-prepared and for library
include files. If the file name is bracketed between "<" and ">", the preprocessor will not search for the
file in the default directory. This reduces the risk of unintended name collisions between user-prepared
and library include files.
Assigning Names

The identifier of every globally visible class, enumeration type, type


Rule 14 definition, function, constant, and variable in a class library is to be placed
in a namespace that corresponds to that class library.
The names of variables, constants, and functions are to begin with a capital
Rule 15 letter.
The names of abstract data types, structures, typedefs, and enumerated
Rule 16 types are to begin with an uppercase letter.
In names which consist of more than one word, the words are written
Rule 17 together and each word that follows the first is begun with an uppercase
letter.

Rule 18 Do not use identifiers which begin with one or two underscores (`_' or `__').
Do not use type names that differ only by the use of uppercase and
Rule 19 lowercase letters.

It is recommended identifiers not be extremely long, to reduce the risk for name collisions when using
tools that truncate long identifiers. At the same time, identifiers should be expressive enough to convey
meaning without requiring too much effort in language deciphering (for example, avoid abbreviations.
This is especially important when dealing with developers of different national origins with different
native languages).
The use of two underscores (`__') in identifiers is reserved for the compiler's internal use according to
the ANSI-C standard.
Underscores (`_') are often used in names of library functions (such as " _main" and "_exit"). In order to
avoid collisions, do not begin an identifier with an underscore.
Recommendation: Industry Standard naming conventions, such as the well-established Hungarian
Notation, provide an excellent set of conventions that conform to the above rules. It is recommended
that such naming conventions be used as the basis for development while, at the same time, flexibility
beyond such conventions (while still adhering to the above rules) be allowed.
Recall that the ultimate goal of the above rules (#14-#19) is to provide for a consistent mechanism by
which identifiers are mnemonic in characterizing their type and purpose.
See the section below entitled Coding Practices for further details.
Style

Classes
The public, protected, and private sections of a class are to be declared in
Rule 20 that order (the public section is declared before the protected section which
is declared before the private section).
No member functions are to be defined within the class definition except
for accessor methods (the “get” and “set” functions that manipulate non-
Rule 21 public member variables)

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.

Example 5 A class definition in accordance with the style rules


class MyString : private Object
{
public:
MyString(); // Default constructor
MyString( const MyString& s ); // Copy constructor
unsigned Length() const;
unsigned GetNoOfChars() { return m_NoOfChars; };
unsigned SetNoOfChars(unsigned N) { return (m_NoOfChars = N); };
// ...
protected:
int CheckIndex( unsigned index ) const;
// ...
private:
unsigned m_NoOfChars;
// ...
};

Functions
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
Rule 22 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).
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 );

Compound Statements
Braces ("{}") which enclose a block are to be placed in the same column,
Rule 24 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.” [Ellemtel]

Flow Control Structures


The code following a case label must always be terminated by a break
Rule 25 statement
A switch statement must always contain a default branch which handles
Rule 26 unexpected cases

Rule 27 Never use goto

Quality Factors
The following rules are designed to ensure the highest level of quality in all software development.
Quality derives from rigorous enforcement of sound design and coding principles as well as intelligent
design of software that is easily tested and debugged.

Debugging
Functions that make assumptions about variables or member data will
Rule 28 validate those assumptions with an ASSERT macro.
Every non-trivial function shall include a TRACE macro denoting the entry
Rule 29 point to that function. In addition, complex portions of code shall include
the TRACE macro in order to track the flow of the function and program.
Every function shall include, at the beginning of the function definition,
code that will log pertinent information. This code shall be delimited by
preprocessor conditionals so that various compilations do not necessarily
Rule 30 include all such logging.
All exception and error handling shall always include logging regardless of
compilation status (e.g., release versus Beta).
Do not use the preprocessor directive #define to obtain more efficient code;
Rule 31 instead, use templated and/or inline functions.
Constants are to be defined using const or enum; never using #define nor
Rule 32 arbitrary literals.
Liberal use of the ASSERT macro imposes no burden on a release build yet provides a robust
mechanism for debugging an application during development and testing.
Likewise, the TRACE macro provides useful information during initial development but is not included
in release builds.
Both mechanism above require only slight additional code / effort on the developer’s part while yielding
significant gains in the testing and debugging of code.
Inline functions have the advantage of often being faster to execute than ordinary functions. The
disadvantage in their use is that the implementation becomes more exposed, since the definition of an
inline function must be placed in an include file for the class, while the definition of an ordinary
function may be placed in its own separate file.
All constants shall be named rather than arbitrary literal values. This allows both for greater
understanding as well as easier maintenance (through centralized definitions). The preprocessor
performs a textual substitution for macros in the source code that is then compiled. This has a number of
negative consequences. For example, if a constant has been defined using #define, the name of the
constant is not recognized in many debuggers. If the constant is represented by an expression, this
expression may be evaluated differently for different instantiations, depending on the scope of the name.
In addition, macros are, at times, incorrectly written.

Code Complexity
Code shall be written to accomplish, at most, a single logically distinct
Rule 32 function per line.
No more than three levels of nested logic shall be used within a single
Rule 33 function. Additional functions shall be used instead, when required.
No more than 9 control flow keywords (e.g., if, else, while, switch) shall be
Rule 34 used in a single function. Additional functions shall be used instead, when
required.
The complexity of an algorithm need not be accompanied by difficult to understand source code.
Source code maintenance and future usability demands that source code be easy to understand; to that
end, the complexity of source code shall be minimized by the above rules.
Coding Practices
The following is a collection of recommended coding practices. These items fall outside the scope of
formalized standards, yet are considerations that should be taken into account when attempting to write
“good” code at GlobalSCAPE, Inc.

ASSERT macros shall be used to check assumed condition. VERIFY


Practice 1 macros shall be used when checks carry out code that must execute in
release mode.
Exception Handling shall be used in all projects to provide high levels of
confidence in the ability of applications to gracefully recover from any
Practice 2 unexpected (or expected!) error conditions. Graceful handling of exception
conditions is highly preferable to GPFs, failed assertions, or simply
unhandled (NOPs) exceptions.
All applications shall have a global exception handler that catches any
exceptions thrown as a result of, but are not caught by the application. A
typical method of accomplishing this would be to create a main function
Practice 3 that wraps the instantiation of the application object in an exception
handling block; or to warp the WinMain message loop in an exception
handler.
Algorithms shall be coded to the standard case with exception handling
Practice 4 used to catch any error conditions. Common sense shall dictate the trade-
offs in exception handling versus conditional execution.
Periodic peer reviews of software shall be done in order to ensure code
quality. These peer reviews are used to solicit ideas, comments,
suggestions, etc. on the various areas that lead to correct and maintainable
code, including (but not limited to):
Adherence to Coding Standards and Naming Conventions
Practice 5
Sound logic
Good Design, esp. Object Oriented
Appropriate Syntax and Semantics
Readability and Understanding, including comments
Program Managers shall “sign-off” on any code as the last step to
delivering it. This results in the PM having accountability for the
responsibility of deliverables meeting the requirement needs.
Practice 6 It is recommended that PMs provide a second walk-through of code prior to
delivering so that they are confident in the correctness of the deliverable
meeting the established “contract” of the associated requirement.
REFERENCES

Ellemtel Rules and Recommendations for http://www.cs.umd.edu/users/cml/cstyle/Ellemtel-rules.html


Programming in C++
GNU C coding standards http://www.gnu.org/prep/standards.html
Indian Hill C Style and Coding Standards, http://www.apocalypse.org/pub/u/paul/docs/cstyle/cstyle.htm
updated
C++ Coding Standard http://www.possibility.com/Cpp/CppCodingStandard.html
Charles Simonyi “Hungarian Notation” http://msdn.microsoft.com/library/techart/hunganotat.htm

Anda mungkin juga menyukai