Gotcha #9: Using Bad Language
When the wider world invaded the comfortably cliquish C++ world some years ago, they brought with them some reprehensible language and coding practices. This item is an attempt to tutor proper, idiomatic C++ diction and behavior.
Diction
Table 1-1 lists the most common diction errors and their correct equivalents.
There is no such thing as a "pure virtual" base class. There are pure virtual functions, and a class that contains or fails to override such a function is abstract.
C++ has no "methods." Java and Smalltalk have methods. When you talk about an object-oriented design and are feeling particularly pretentious, you may use the terms "message" and "method," but when you get down to discussing a C++ implementation of your design, use the terms "function call" and "member function."
Some otherwise reliable C++ experts (you know who you are) use the term "destructed" as an orthogonal analog to "constructed." That's just bad English. The term is "destroyed."
C++ does indeed have cast (or type conversion) operators—four of them, in fact: (static_cast, dynamic_cast, const_cast, and reinterpret_cast). However, the term "cast operator" is often incorrectly used to refer to a member conversion operator that specifies how a class object may be implicitly converted to another type:
class C {
operator int *()const; // a conversion operator
// . . .
};
Table 1-1. Common diction errors and their correct equivalents
|
Pure virtual base class
|
Abstract class
|
|
Method
|
Member function
|
|
Virtual method
|
???
|
|
Destructed
|
Destroyed
|
|
Cast operator
|
Conversion operator
|
Of course, it's also permissible to invoke a conversion operator explicitly with a cast operator, provided you know which is which.
See also Gotcha #31 for a discussion of const pointer versus pointer-to-const sloppiness.
Null Pointers
Once upon a time, there was potential for disaster in C++ programs if the preprocessor symbol NULL was used to represent the null pointer:
void doIt( char * );
void doIt( void * );
C *cp = NULL;
The trouble was that NULL would be defined in various ways on different platforms:
#define NULL ((char *)0)
#define NULL ((void *)0)
#define NULL 0
These various definitions wreaked havoc with portability of C++ programs:
doIt( NULL ); // platform-dependent or ambiguous
C *cp = NULL; // error?
In fact, there is no way to represent a null pointer directly in C++, but we're guaranteed that the numeric literal 0 is convertible to a null pointer value for any pointer type. That is what C++ programmers traditionally used to ensure the portability and correctness of their code. Now the standard indicates that definitions like (void *)0 are not allowed, so this isn't so much a technical issue with the use of NULL (except that it's a preprocessor symbol and is therefore looked on askance). However, real C++ programmers still use 0 to represent the null pointer value. Any other usage will mark you as hopelessly démodé.
Acronyms
C++ programmers have the acronym disease, though perhaps not to the extent managers do. Table 1-2 may be of use the next time one of your colleagues tells you that the RVO won't be applied to a POD, so you'd better define a copy ctor.
Table 1-2. Meanings of common acronyms
|
POD
|
Plain old data, a C struct
|
|
POF
|
Plain old function, a C function
|
|
RVO
|
Return value optimization
|
|
NRV
|
Named RVO
|
|
ctor
|
Constructor
|
|
dtor
|
Destructor
|
|
ODR
|
One definition rule
|
|