5. Assigning Names
- Rule 12
- The identifier of every globally
visible class, enumeration type, type definition, function, constant,
and variable in a class library is to begin with a prefix that is
uniquefor the library.
- Rule 13
- The names of variables, constants,
and functions are to begin with a lowercase letter.
- Rule 14
- The names of abstract data types,
structures, typedefs, and enumerated types are to begin
with an uppercase letter.
- Rule 15
- In names which consist of more than
one word, the words are written together and each word that
follows the first is begun with an uppercase letter.
- Rule 16
- Do not use identifiers which begin
with one or two underscores ('
_ ' or '__ ').
- Rule 17
- A name that begins with an uppercase
letter is to appear directly after its prefix.
- Rule 18
- A name that begins with a
lowercase letter is to be separated from its prefix using an underscore
('
_ ').
- Rule 19
- A name is to be separated from its
suffix using an underscore ('
_ ').
- Rec. 14
- Do not use typenames that differ only
by the use of uppercase and lowercase letters.
- Rec. 15
- Names should not include abbreviations
that are not generally accepted.
- Rec. 16
- A variable with a large scope should
have a long name.
- Rec. 17
- Choose variable names that suggest
the usage.
- Rec. 18
- Write code in a way that makes it
easy to change the prefix for global identifiers.
- Rec. 19
- Encapsulate global variables and
constants, enumerated types, and typedefs in a class.
In this chapter, it is important to distinguish between identifiers and
names.
[See terminology 1!]
The name is
that part of an identifier that shows its meaning. An identifier consists
of a prefix, a name, and a suffix (in that order). The prefix and the
suffix are optional. A suffix is only used by tools that generate C++
code, to avoid name collisions with user-written C++ code and is not
given further consideration here.
It is recommended identifiers not be extremely long, to reduce the
risk for name collisions when using tools that truncate long identifiers.
The Unix command ar truncates file
names that are longer than 15 characters.
Cfront normally modifies generated C-identifiers that are longer than 31
characters by truncating them and adding a hash value that is generated
from the truncated part of the string.
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.
One rule of thumb is that a name which cannot be pronounced is a bad
name. A long name is normally better than a short, cryptic name, but
the truncation problem must be taken into consideration. Abbreviations
can always be misunderstood. Global variables, functions and constants
ought to have long enough names to avoid name conflicts, but not too long.
Classes should be named so that "object.function" is easy to read
and appears to be logical.
There are many class libraries available for purchase and there may
be tens of thousands of classes in a large project!! Because of this, it
is important to be careful that name collisions do not occur. One way
of preventing collisions is to have strict rules for assigning names
to globally visible objects (such as our use of a prefix). In this
way, classes from several different class libraries may be used at the
same time.
Names for the following types of objects are to be prefixed:
- Type names (classes,
typedef s, enum s,
struct s, union s, etc.)
- Global variables and constants
- Function names (not member functions names)
- Preprocessor macros (
#define )
The use of prefixes can sometimes be avoided by using a class to
limit the scope of the name. Static variables in a class should be used
instead of global variables and constants, enumerated data types, and
typedefs. Although nested classes may be used in C++, these give rise
to too many questions (in connection with the language definition) to
be able to recommend their use.
- Exception to Rule 12
- No exceptions.
- Exception to Rule 13
- No exceptions. (At times, an identifier
begins with an abbreviation written in uppercase letters, to emphasize
the way in which the name is used. Such an abbreviation is considered
to be a prefix).
- Exception to Rule 14
- If the last letter in a word is in uppercase,
an underscore is to be used as a word separator.
- Exception to Rule 15
- No exceptions.
- Exception to Rule 16
- No exceptions.
- Exception to Rule 17
- No exceptions.
- Exception to Rule 18
- No exceptions.
- Exception to Rule 19
- No exceptions.
Example 9: Exception using compound names
const char* functionTitle = "EUA_Special";
int currentIO_Stream = 1; // Last Character in currentIO is in uppercase!
Example 10: Choice of names
int groupID; // instead of grpID
int nameLength; // instead of namLn
PrinterStatus resetPrinter; // instead of rstprt
Example 11: Ambiguous names
void termProcess(); // Terminate process or
// terminal process?
Example 12: Names having numeric characters can cause errors which are difficult to locate.
int I0 = 13; // Names with digits can be
int IO = I0; // difficult to read.
Example 13: Definition of a class in the class library Emc2
class Emc2Class
{
public:
Emc2Class(); // Default constructor
// ...
private:
int id;
// ...
};
Example 14: One way to avoid global functions and classes
// Instead of declaring:
void Emc2_myFunc1();
void Emc2_myFunc2();
class Emc2MyClass { /* ... */ };
// Encapsulate the functions using an abstract class:
class Emc2
{
public:
static void myFunc1();
static void myFunc2();
class MyClass { /* ... */ };
private:
virtual dummy() = 0; // Trick to make the class abstract
};
// Now, functions and classes may be accessed by using the scope-operator:
Emc2::myFunc1();
Emc2::myFunc2();
Emc2::MyClass myObject;
|