| | Bu bolumde her ay amator
C++ siteleri ve dersleri yayınlayacagız.
C de mouse supporta ihtiyacınız
varsa |
|
|
|
memman2c.zip |
XMS/EMS/Virtual *Flat* Memory for C++/C
|
bfast11.zip |
FREE Btrieve fully functioning C++ library |
bspline.zip |
C++ src for simple b-spline curve algorithm
|
build100.zip
|
Time,date,sys,str,mouse,xms,kbd,scr routines
|
cachecl1.zip
|
Cache class implementation (Borland C++ 4.5)
|
calcplus.zip
|
Interpreter of procedural lang., C++ class lib
|
cbc150d.zip
|
CMATH: Complex math lib for Borland C/C++
|
ccl110je.zip
|
DOS coroutine class library for Borland C++
|
chartp10.zip
|
C++ object-oriented chart parser w/ source
|
cisam120.zip
|
B+Tree/ISAM Database progrmming systm for c
|
cptuts22.zip
|
Coronodo C++ Tutorial: Source examples, 1/2
|
cptutt22.zip
|
Coronodo C++ Tutorial: Tutorial text files 2/2
|
cslib211.zip
|
Database library for C++ developers
|
deadgame.zip
|
Strategic boardgame with C++ source & theory
|
diskar1b.zip
|
Creating arrays on disk with Borland C++
|
objeas3a.zip
|
Graphic/text user interface C++ library, 1of2
|
objeas3b.zip
|
Graphic/text user interface C++ library, 2of2
|
dos_win1.zip
|
Windows-like GUI for DOS. BC++ 3.1 source
|
cpmatr11.zip
|
C++ matrix template class library (source)
|
c++ dersleri
tutorial 1
1 Introduction
This document list C++ coding recommendations used by the Geotechnical
Software Services development organisation.
The recommendations are based on established standards, individual
experience, local requirements/needs as well as suggestions given in [1]
- [4].
There are several reasons for introducing a new guideline rather than just
refering to the ones above. Main reason is that these guides are far to general
in their scope and that more specific rules (espesially naming rules) must be
established locally. In addition, most of these guides mixes style issues with
C++ language technical issues in a somewhat confusing manner.
This document does not contain any C++ technical recommendations at all, but
focuses mainly on programming style.
1.1 Layout of the
Recommendations.
The recommendations are grouped by topic and each recommendation is numbered
to make it easier to refer to during reviews.
Layout of the recommendations are as follows:
Guideline short description |
Example if applicable |
Motivation, background and additional information. |
The motivation section is important. Coding standards and guidelines tend to
start "religious wars", and it is important to state the background
for the recommendation.
1.2 Recommendation Importance
In the guideline sections the terms must, should and can have
special meaning. A must requirement must be followed, a should is
a strong recommendation, and a can is a general guideline.
2 General Recommendations
1. Any violation to the guide is allowed if it enhance
readability. |
|
The main goal of the recommendation is to improve
readability and thereby the understanding and the maintainability and
general quality of the code. It is impossible to cover all the specific
cases in a general guide and the programmer should be flexible. |
2. The rules can be violated if there are strong
personal objections against them. |
|
The attempt is to make a guideline, not to force a
particular coding style onto individuals. |
3 Naming Conventions
3.1 General Naming Conventions
3. Names representing types must be in mixed case
starting with upper case. |
Line, FilePrefix |
Common standard in C++ programming environments. |
4. Variable names must be in mixed case starting with
lower case. |
line, filePrefix |
Common standard in C++ programming environments.
Makes variables easy to distinguish from types, and effectively resolve
potential naming collision as in the declaration Line *line; |
5. Named constants (including enumeration values) must
be all uppercase using underscore to separate words. |
MAX_ITERATIONS, COLOR_RED |
Common standard in C++ programming environments. |
6. Function names must be mixed case starting with lower
case. |
getName(), computeTotalWidth() |
This is identical to variable names, but functions
in C++ are already distingushable from variables by their specific form. |
7. Common abbreviations should not be uppercase when
used as name [4]. |
exportHtmlSource(); // NOT: exportHTMLSource();
openDvdPlayer(); // NOT: openDVDPlayer(); |
Using all uppercase for the base name will give
conflicts with the naming conventions given above. A variable of this
type must be named dVD, hTML etc. which obviously is not very readable.
Another problem is illustrated in the examples above; When the name is
connected to another, the readbility is seriously reduced; The word
following the abbreviation does not stand out as it should. |
8. Global variables should be prefixed by g_. |
g_mainWindow, g_applicationContext |
Enhance readability because it gives the reader
immediate clue about where the variable is defined and how it is to be
used. To further emphasize their global nature they should be prefixed
by "::" on every access. |
9. Private class variables should have _ suffix. |
class SomeClass {
private:
int length_;
} |
The reason is twofold. First it enhance the
readability of the code because it is immediately apparent if a given
variable is private to the object or not. Second it resolves the problem
of finding reasonable variable names for access functions:
SomeClass::setDepth (int depth)
{
depth_ = depth;
}
|
10. All names should be written in english. |
fileName; // NOT: filNavn |
English is the prefered language for international
development. |
3.2 Specific Naming Conventions
11. Types must be prefixed by their module name. |
GppLine, UiPrinterDialog, IoFileDescriptor |
Enhances readability since it can be easily seen
where the code for an object resides. Also avoid naming conflicts since
different modules often will have types with the same name. |
12. Variables with a large scope should have long names,
variables with a small scope can have short names [1]. |
|
Scratch variables used for temporary storage or
indices are best kept short. A programmer reading such variables should
be able to assume that its value is not used outside a few lines of
code. |
13. The name of the object is implicit, and should be
avoided in a function name. |
line->getLength(); // NOT: line->getLineLength(); |
The latter seams natural in the class declaration,
but prove superfluous in use, as shown in the example. |
14. The term compute should be used in functions
where something is computed. |
valueSet->computeAverage(); matrix->computeInverse() |
Give the reader the immediate clue that this is a
potential time consuming operation, and if used repeatedly, he might
consider caching the result. Consistent use of the term enhance
readability. |
15. The term find should be used in functions
where something is looked up. |
vertex->findNearestVertex(); matrix->findMinElement(); |
Give the reader the immediate clue that this is a
simple look up function with a minimum of computations involved.
Consistent use of the term enhance readability. |
16. The terms get/set should be used where an
attribute is accessed directly. |
employee->getName();
matrix->getElement(2, 4);
employee->setName (name); matrix->setElement (2, 4, value); |
These functions are typically declared inline. |
17. The term initialize should be used where an
object or a concept is established. |
printer->initializeFontSet(); |
The american initialize should be preferred
over the english initialise. Abbreviation init should be
avoided. |
18. For X Motif widget variables, suffix [widgettype]W
should be used. |
widthScaleW, nameTextW, leftScrollbarW, mainFormW, fileToggleW,
minLabelW, printerDialogW |
Enhance readability since the name gives the user an
immediate clue of the type of the variable and thereby the objects
resources. |
19. List suffix should be used on names
representing a list of objects. |
vertex (one vertex), vertexList (a list
of vertices) |
Enhance readability since the name gives the user an
immediate clue of the type of the variable and the operations that can
be performed on the object. Simply using the plural form of the base
class name for a list (matrixElement (one matrix element), matrixElements
(list of matrix elements)) must be avoided since the two only
differ in a single character and are thereby difficult to distinguish. A
list in this context is the compound data type that can be
traversed backwards forwards etc (typically an STL vector). A
plain array is simpler. The suffix Array can be used to denote an
array of objects. |
20. n prefix should be used for variables
representing a number of objects. |
nPoints, nLines |
Enhance readability. |
21. is prefix can be used for boolean variables
and functions. |
isSet, isVisible, isFinished, isFound, isOpen |
Enhance readability. Using is prefix solves a
common problem of choosing bad boolean names like status or
flag. isStatus or isFlag simply doesn't fit,
and the programmer is forced to chose more meaningful names. |
22. No suffix should be used for variables
representing an entity number. |
tableNo, emplyeeNo |
Enhance readability. |
23. Complement names must be used for complement
functions [1]. |
get/set, add/remove, create/destroy, start/stop, insert/delete,
increment/decrement, old/new, begin/end, first/last, up/down, min/max,
next/previous, old/new, open/close, show/hide |
Reduce complexity by symmetry. |
24. Abbreviations in names should be avoided. |
computeAverage(); // NOT: compAvg(); |
Enhance readability. |
25. Naming pointers specifically should be avoided. |
Line *line; // NOT: Line *pLine; or Line *linePtr;
etc. |
Many variables in a C/C++ environment are pointers,
so a convention like this is almost impossible to follow. Also objects
in C++ are often oblique types where the specific implementation should
be ignored by the programmer. Only when the actual type of an object is
of special significance, the name should empahsize the type. |
26. Negated boolean variable names must be avoided []. |
bool error; // NOT: noError
bool found; // NOT: notFound |
The problem arise when the logical not operator is
used and double negative arises. It is not immediately apparent what !noError
means. |
27. Enumeration constants should be prefixed by a common
type name. |
enum Color {
COLOR_RED,
COLOR_GREEN,
COLOR_BLUE
}; |
This gives additional information of where
declaration can be found, which constants belong together, and what type
the constants represent. |
28. Functions should be named after what they return and
procedures after what they do. |
|
Increase readability. Makes it clear what the unit
should do and especially all the things it is not supposed to do. This
again makes it easier to keep the code clean of side effects. |
4 Files
4.1 Source Files
29. C++ source files should have the extension .C
and header files extension .h. |
definition.C, declaration.h |
This is an accepted C++ standard for file extension.
The standard of using .cc, .c++, CXX for source could equally well have
been chosen, .C is preferred since it makes file names shorter. |
30. Classes can be declared in individual files with the
file name matching the class name [2]. For source files, the main
(including constructors destructors and main public interface)
implementation of a class can have the class the name, additional files
can be derived from the class name. |
UiPrinter.h UiPrinter.C UiPrinterSetup.C UiPrinterColor.C |
Given a variable of a given type, it is easy for the
programmer to find where it is defined and declared. |
31. File content must be kept within 80 columns. |
|
80 columns are common dimension for editors,
terminal emulators, printers and debuggers and files that are shared
between several people should keep within these constraints. It improve
readability when unintentional line breaks are avoided when passing a
file between programmers. |
32. TAB and page break characters etc. must be avoided. |
|
These characters are bound to cause problem for
editors, printers, terminal emulators or debuggers when used in a
multi-programmer, multi-platform environment. |
33. The incompleteness of split lines must be made
obvious [1]. |
totalSum = a + b + c +
d + e);
function (param1, param2,
param3);
setText ("Long line split"
"into two
parts.");
for (tableNo = 0; tableNo < maxTable;
tableNo += tableStep) |
Split lines occurs when a statement exceed the 80
column limit given above. It is difficult to give rigid rules for how
lines should be split, but the examples above should give a general
hint. |
4.2 Include Files and Include Statements
34. Header files must include a construction that
prevents multiple inclusion. The convention is an all uppercase
construction of the module name, the file name and the h suffix. |
#ifndef MOD_FILENAME_H
#define MOD_FILENAME_H
:
#endif |
The construction is to avoid compilation errors. The
name convention is common practice. The construction should appear in
the top of the file (before the file header) so file parsing is aborted
immediately and compilation time is reduced. |
35. Include statements should be sorted and grouped.
Sorted by their hierarchical position in the system with low level files
included first. Leave an empty line between groups of include
statements. |
#include <fstream>
#include <iomanip>
#include <Xm/Xm.h>
#include <Xm/ToggleB.h>
#include "ui/dialog.h"
#include "ui/window.h" |
In addition to show the reader the individual
include files, it also give an immediate clue about the modules are
involved. |
36. Include statements must be located at the top
(immediately after the file header) of a file only. |
|
Common practice. Avoid unwanted compilation side
effects by "hidden" include statements deep into a source
file. |
5 Statements
5.1 Types
37. Types that are local to one file only can be
declared inside that file. |
|
Enforces information hiding. |
38. The parts of a class must be sorted public, protected
and private [2][3]. All sections must be identified
explicitly. Not applicable sections should be left out. |
|
The ordering is "most public first"
so people who only wish to use the class can stop reading when they
reach the protected/private sections. |
39. Type conversions must always be done explicitly.
Never relay on implicit type conversion. |
floatValue = (float) intValue; // NOT:
floatValue = intValue; |
By this, the programmer indicates that he is aware
of the different types involved and that the mix is intentional. |
5.2 Variables
40. All variables should be declared in the beginning of
their scope and in the smallest scope possible. |
|
Enhance readability. The reader will always know
where to look for the variable declaration, and will immediately know
its scope based on the location of the declaration. |
41. Variables must never have dual meaning. |
|
Enhance readability by ensuring all concepts are
represented uniquely. Reduce chance of error by side effects. |
42. Use of global variables should be minimized. |
|
In C++ there are no reason global variables need to
be used at all. The same is the fact for global functions or file scope
(static) variables. |
43. Class variables must never be declared public. |
|
The concept of C++ information hiding and
encapsulation is violated by public variables. Use private variables and
access functions instead. A side effect of this recommendation is that
C++ structs should not be used at all. A class should always be used
instead. |
44. Related variables of the same type can be declared
in a common statement [3].
Unrelated variables should not be declared in the same statement. |
float x, y, z;
float revenueJan, revenueFeb, revenueMar; |
The common requirement of having declarations on
separate lines is not useful in the situations like the ones above. It
enhance readability to group variables like this. |
45. C++ pointers should have their pointer symbol (*)
next to the variable name rather than to the type name [3]. |
float *x; // NOT: float* x; |
It can be discussed weather a pointer is a variable
of a pointer type (float* x) or a pointer to a given type (float
*x). Important in the recommendation given though is the fact that it is
impossible to declare more than one pointer in a given statement using
the first approach. I.e. float* x, y, z; is equivalent with float *x;
float y; float z; |
46. Implicit test for 0 should not be used other
than for boolean variables and pointers. |
if (nLines == 0) // NOT: if (nLines)
if (value == 0.0) // NOT: if (value) |
It is not necessarily defined by the computer that
ints and floats 0 are implemented as binary 0. Also, by using explicit
test the statement give immediate clue of the type being tested. It is
common also to suggest that pointers shouldn't test implicit for 0
either, i.e. if (line == 0) instead of if (line). The
latter is regarded as such a common practice in C/C++ however that it
can be used. |
47. Variables should be kept alive for as short a time
as possible. |
|
Keeping the operations on a variable within a small
scope, it is easier to control the effects and side effects of the
variable. |
5.3 Loops
48. Only loop control statements must be included in the
for() construction. |
sum = 0;
// NOT: for (i=0, sum=0; i<100; i++)
for (i=0; i<100; i++) //
sum += value[i];
sum += value[i]; |
Increase maintainability and readability. Make it
crystal clear what controls the loop and what the loop contains. |
49. Loop variables should be initialized immediately
before the loop []. |
done = false;
// NOT: bool done = false;
while (!done) { // :
:
// while (!done) {
}
// :
} |
|
50. The use of break and continue in loops
should be minimized. |
|
These constructs are in same class as goto. Should
only be used if they prove to have higher readability than their
structures counterpart. |
51. Explicit continue should be used in empty
loops [3]. |
while (*p++ = *q++) // NOT: while (*p++ = *q++);
continue; |
This makes it obvious that the loop is left emty
intentionally. |
52. The form for (;;) should be used for
empty loops [3]. |
for (;;) {
// NOT: while (1) {
:
// :
}
// } |
This form is better than the functionally equivalent
while (TRUE) or while (1) since they imply a test
against TRUE (or 1), which is neither necessary nor
meaningful. |
5.4 Conditionals
53. Complex conditional expressions must be avoided.
Introduce temporary boolean variables instead [1]. |
if ((elementNo < 0) || (elementNo > maxElement)||
elementNo == lastElement) {
:
}
should be replaced by:
finished = (elementNo < 0) || (elementNo
> maxElement);
repeatedEntry = elementNo == lastElement;
if (finished || repeatedEntry) {
:
}
|
By assigning boolean variables to expressions, the
program gets automatic documentation. The construction will be easier to
read and to debug. |
54. The nominal case should be put in the if-part
and the exception in the else-part of an if statement [1]. |
error = readFile (fileName);
if (!error) {
:
}
else {
:
} |
Makes sure that the exceptions don't obscure the
normal path of execution. This is important for both the readability and
performance. |
55. The conditional should be put on a separate line. |
if (done)
// NOT: if (done) doCleanup();
doCleanup(); |
This is for debugging purposes. When writing on a
single line, it is not apparent weather the test is really true or not. |
56. Executable statements in conditionals must be
avoided. |
fp = open (fileName, "w"); // NOT: if
(!(fp = open (fileName, "w"))) {
if (!fp) {
// :
:
// }
} |
Conditionals with executable statements are just
very difficult to read. This is especially true for programmers new to
C/C++. |
5.5 Miscellaneous
57. The use of magic numbers in the code should be
avoided. Numbers other than 0 and 1 should be considered
declared as named constants instead. |
|
If the number does not have an obvious meaning by
itself, the readability is enhanced by introducing a named constant
instead. |
58. Goto should not be used. |
|
Goto statements violates the idea of structured
code. Only in some very few cases (for instance breaking out of deeply
nested structures) should goto be considered, and only if the
alternative structured counterpart is proven to be less readable. |
59. #defines should not be used. |
|
#defines are not part of the programming language,
and C++ have constructs for concepts solved by the common #define
statements; named constants and function overloading. |
60. "0" should be used instead of
"NULL". |
|
NULL is part of the standard C library, but
is made obsolete in C++. |
6 Layout and Comments
6.1 Layout
61. Basic indentation should be 2. |
for (i=0; i<nElements; i++)
a[i] = 0; |
Indentation of 1 is to small to emphasize the
logical layout of the code. Indentation larger than 4 makes deeply
nested code difficult to read and increase the chance that the lines
must be split. Choosing between indentation of 2, 3 and 4, 2 and 4
are the more common, and 2 chosen to reduce the change of splitting code
lines. |
62. Block layout should be as illustrated in
example 1 below (recommended) or example 2, and must not be as shown in
example 3 [4]. Function blocks must use the block layout of example 2. |
while (!done) {
doSomething();
done = moreToDo();
}
|
while (!done)
{
doSomething();
done = moreToDo();
}
|
while (!done)
{
doSomething();
done = moreToDo();
}
|
Example 3 introduce an extra indentation
level which doesn't emphasize the logical structure of the code as
clearly as example 1 and 2. |
63. The function type should be put in the left column
immediately above the function name. |
void
MyClass::function (void)
{
:
} |
This makes it easier to spot function names within a
file since one can assume that they all start in the first column. |
6.2 White Space
64.
- Conventional operators should be surrounded by a space character.
- C++ reserved words should be followed by a white space.
- Commas should be followed by a white space.
- Colons should be surrounded by white space.
- Semicolons in for statments should be followed by a space character. |
a = (b + c) * d;
// NOT: a=(b+c)*d
while (true) {
// NOT: while(true) ...
doSomething (a, b, c, d); // NOT: doSomething (a,b,c,d);
case 100 :
// NOT: case 100:
for (i = 0; i < 10; i++) { // NOT: for (i=0;i<10;i++){ |
Makes the individual components of the statements
stand out. Enhance readability. It is difficult to give a complete list
of the suggested use of whitespace in C++ code. The examples above
however should give a general idea of the intentions. |
65. Function names should be followed by a white space
when it is followed by another name. |
doSomething (currentFile); // NOT:
doSomething(currentFile); |
Makes the individual names stand out. Enhance
readability. When no name follows, the space can be omitted (doSomething())
since there is no doubt about the name in this case. The same is the
case for the dereference operator: file.create() or
file->create(). |
66. Logical units within a block should be separated by
one blank line. |
|
Enhance readability by introducing white space
between logical units of a block. |
67. Declaration part of a block should be separated by
the executable block by two blank lines. |
|
Enhance readability by introducing white space
between logical units of a block. By making the space larger than for
between logical units, the declaration part of the code will stand out. |
68. Functions should be separated by 3-5 blank lines. (5
recommended) |
|
By making the space larger than space within a
function, the functions will stand out within the file. |
69. Variables in declarations should be left aligned. |
AsciiFile *file;
int nPoints;
float x, y; |
Enhance readability. The variables are easier to
spot from the types by alignment. |
70. There are a number of places in the code where white
space can be included to enhance readability even if this violates
common guidelines. Many of these cases has to do with code alignment.
General guidelines on code alignment are difficult to give, but the
examples below should give a general clue. |
if (a == lowValue)
compueSomething();
else if (a == mediumValue) computeSomethingElse();
else if (a == highValue) computeSomethingElseYet();
value = (potential *
oilDensity) / constant1 +
(depth
* waterDensity) / constant2 +
(zCoordinateValue *
gasDensity) / constant3;
minPosition = computeDistance (min,
x, y, z);
averagePosition = computeDistance (average, x, y, z);
switch (value) {
case PHASE_OIL : strcpy (string, "Oil");
break;
case PHASE_WATER : strcpy (string, "Water"); break;
case PHASE_GAS : strcpy (string, "Gas");
break;
} |
Again: Any construction that enhance readability is
OK! |
6.3 Comments
71. Tricky code should not be commented but rewritten!
[1] |
|
The use of comments should in general be minimised
by making the code self-documenting by names and an explicit logical
structure. |
72. All comments should be written in english [2]. |
|
In an international environment english is the
preferred language. |
73. Use // for all comments, also multiline
comments. |
// Comment spanning
// more than one line |
Since multilevel C-commenting is not supported,
using // comments ensure that it is always possible to out comment
entire sections of a file using /* */ for debugging purposes etc. |
74. Comments should be included relative to their
position in the code. [1] |
while (true) {
// NOT: while (true) {
// Do something //
// Do something
something();
//
something();
}
// } |
This is to avoid that the comments breaks the
logical structure of the program. |
75. File headers should be included as follows: |
//********************************************************************
//
// math/myfile.C
//
// (C) Copyright Geotechnical Software Services
// Castors gate 37, 4021 Stavanger, Norway
//
// Purpose:
// Define the class MyClass.
//
// Description:
// Utility functions for mathematical
handling purposes.
//
// History:
// 12/08/99 Created (joe)
// 24/09/99 Added invertMatrix() (dave)
//
//******************************************************************** |
The part written in black constitutes the file
header template. The intention is to create a common header that gives
valuable information and is easy to maintain. At the top the filename
should be included to make it easier to identify the file in printouts
etc. The fields Purpose and Description are free form and should be
included according to the complexity of the file content. History entry
should include all non-trivial changes to the file with specific data in
the format as shown, and a name tag that identify the programmer. |
76. Function headers should be included for non-trivial
functions only. The proposed format: |
//********************************************************************
//
// Purpose:
// Export data from a postscript file.
//
// Parameters:
// fileName (i) - The file to import
from
// source (o) - The
postscript source read
// error (r) - True
if an error occured, False otherwise
//
// Description:
// Open the specified file. Scan
forward to each keyword and pass
// control to appropriate sub function
to read actual data.
//
//******************************************************************** |
The part written in black constitutes the function
header template. The intention is to create a common header that gives
valuable information and is easy to maintain. The purpose field should
summarize the function content in a single line. If this is not
possible, a redesign should be considered. The parameter list should
include a tag identifying the parameter as either in (i), out (o) or
return (r). The description section should contain information about the
algorithms used etc. Function headers should be omitted for trivial
functions like access functions etc. |
|