DOC

C++ Programming Guidelines

By Ethel Gonzales,2014-06-17 13:01
12 views 0
C++ Programming GuidelinesC+

    C++ Programming Guidelines

    John M. Dlugosz

    26-August-2001

    Copyright ? 2001 by John M. Dlugosz

    http://www.dlugosz.com

    This publication may be used freely, with attribution, for all purposes including distributing printed and electronic copies, provided no fee is charged for such distribution, this copyright notice and information remains intact, and any changes to the content are clearly marked as non-original material. Printed copies should be made with the correct fonts, as indicated below.

    The content in this document may be used as a base for derivative works, provided this document is cited.

    This document uses the following fonts, all of which come with Windows, Microsoft Word ’97, the associated “value pack”, and may be available on Microsoft's web site:

    Bookman Old Style

    Comic Sans MS

    Arial

    Arial Black

    Arial Rounded MT Bold

    Lucida Sans

    Lucida Sans Typewriter

    Wingdings

    Wingdings 2

    Franklin Gothic Demi Cond

    Symbol

Contents

    Introduction ..................................................................................................... 6 Considerations .............................................................................................. 6 Scope ............................................................................................................ 7 C++ Header Files .............................................................................................. 8 Standard Structure of a .H file ...................................................................... 8 Header Content Restrictions .......................................................................... 9 Format of the #include statement ................................................................ 11 Minimize Compilation Dependencies Between Files ..................................... 12 Names ............................................................................................................ 13 Globally Unique Identifier Names ................................................................ 13 DLL Names .................................................................................................. 14 Usable #define Names ................................................................................. 15 Reserved Names .......................................................................................... 15 Comments ...................................................................................................... 17 Be Useful ..................................................................................................... 17 Formatting Of Comments ............................................................................ 18 No Verbose Comments ................................................................................ 19 Don‘t Mix Code With Documentation ........................................................... 19 Revision Control Information ....................................................................... 22 C style vs. C++ Style .................................................................................... 23 Commenting Out Blocks of Code ................................................................. 23 Namespaces ................................................................................................... 24 DLLs ............................................................................................................... 25 Embed Version Information in DLL ............................................................. 25 Exporting Symbols ...................................................................................... 29 DLL-specific Resources ................................................................................ 33 Initialization and Shutdown Issues .............................................................. 33 Linking ........................................................................................................ 36 Compiler Options............................................................................................ 37 Standard Build Options ............................................................................... 37 Options for Efficient Code ............................................................................ 39 Options for Programmer Convenience .......................................................... 39 Run-Time Library in a DLL or Statically Linked? ......................................... 40 Error Handling ............................................................................................... 41 Write Pro-EH Code ...................................................................................... 41 Exception Specifications .............................................................................. 41 Functions Return Results ............................................................................ 41 Constructors and Destructors ..................................................................... 41 Catch References ......................................................................................... 41 Don‘t Throw Pointers ................................................................................... 41 Use Standard Exception Types .................................................................... 41 Internationalization ........................................................................................ 42 Don‘t Assume the Whole World is Latin-1 .................................................... 42 Watch Out For Multibyte Characters ........................................................... 42 Distinguish OEM and ANSI Character Set ................................................... 43 C++ Programming Guidelines Page 2 John M. Dlugosz 18-July-1999

     C++ Language Usage ...................................................................................... 45

    Casting ........................................................................................................ 45 Error Checking is Good ............................................................................... 45 Avoid Macros ............................................................................................... 45 Use Smart Pointers ...................................................................................... 47

     Use Value Semantics ................................................................................... 47

    Promote Strong Type Checking .................................................................... 47 Use RTTI, Not Home-Brew ........................................................................... 47 Memory Management ..................................................................................... 48 Match frees with allocations ........................................................................ 48 Exceptions vs. NULL for ‗new‘ ...................................................................... 48 C++ Declarations ............................................................................................ 51 Avoid Global Constructors and Destructors ................................................. 51 Declaring Const Objects .............................................................................. 54 Choosing Names .......................................................................................... 54 Boolean variables ........................................................................................ 55 Enumeration Types ..................................................................................... 55 Use Readable Enums Rather Than Bool ...................................................... 56 Use Anonymous Namespaces for File-Local Things ...................................... 56 Pointers vs. References ................................................................................ 56 Formatting Pointer/Reference Declarations ................................................. 56 Declare (and initialize) Variables Where Needed ........................................... 56 Avoid ―Out‖ Parameters ............................................................................... 57 Don‘t Use (void) Parameter List .................................................................... 57 Overloading .................................................................................................... 58 When functions do the same thing but operate on different types they should have the same name. ................................................................................... 58 C++ Statements .............................................................................................. 59 Switch Statements....................................................................................... 59 Return Statements ...................................................................................... 59 Goto Statements .......................................................................................... 59 Classes ........................................................................................................... 60 Canonical Object Form ................................................................................ 60 General Constructor Issues ......................................................................... 61 General Destructor Issues ........................................................................... 61 Default Constructor Issues .......................................................................... 63 Copy Constructor Issues ............................................................................. 63 prefix and postfix ++ and ?? ........................................................................ 63 Assignment Operator Issues ........................................................................ 63 ―other‖ copy functions ................................................................................. 64 Use ‗explicit‘ Constructors ........................................................................... 65 Use Objects To Wrap Resources .................................................................. 66 C++ Libraries .................................................................................................. 67 Old vs. New Standard Headers .................................................................... 67 Use new/delete for Memory Management .................................................... 67 STL is Like Pointers ..................................................................................... 67 Memory Management ..................................................................................... 68 Encapsulate Non-Standard Memory Management ....................................... 68 Use Proper Vector/Scalar Form of Delete..................................................... 68 Class-Specific New/Delete ........................................................................... 68 C++ Programming Guidelines Page 3 John M. Dlugosz 18-July-1999

     Placement Arguments (Overloading New) ..................................................... 68

    Errors in Operator New ............................................................................... 68 Threading Issues ............................................................................................ 69 Thread-Specific Data ................................................................................... 69 Mutual Exclusion ........................................................................................ 69 Static Local Variables .................................................................................. 70 Disks and Files ............................................................................................... 71 Disk and File Size ........................................................................................ 71 File Name Delimiters ................................................................................... 71 File Names .................................................................................................. 72 Templates ....................................................................................................... 73 Put Common Code Into a Non-Template Base Class .................................... 73 Miscellaneous Conventions ............................................................................. 74 Dates ........................................................................................................... 74 Cause and Effect Should Be Close Together ................................................ 74 Expressiveness ............................................................................................ 74 Windows 95 vs. NT ......................................................................................... 76 ANSI or Unicode Version of API ................................................................... 76 Functions Available only in NT or 95 ........................................................... 76 Win32 Guidelines ........................................................................................... 78 File Installation Locations............................................................................ 78 Managing Common Files ............................................................................. 78 Consistent use of TCHAR ............................................................................ 80 Win32 Faux Pas‘s ........................................................................................... 82 Tray Icons Should Watch for Restarts.......................................................... 82 Appendix A: Reprinted Papers ........................................................................ 84 Two-stage Destructors ................................................................................. 85 Appendix B: Bibliography ............................................................................... 87 Appendix C: References .................................................................................. 88 Appendix D: Listings ....................................................................................... 89 CheckOEM .................................................................................................. 89 Index .............................................................................................................. 90

    C++ Programming Guidelines Page 4 John M. Dlugosz 18-July-1999

    Rule Concordance Rule 1. Use the standard structure for a .H file. .............................................. 9

    Rule 2. Use UUID format (preferred) or standard ―user friendly‖ format for

    global names. .................................................................................... 13

    Rule 3. Don't use names that begin with an underscore or contain a double-

    underscore. ....................................................................................... 16

    Rule 4. No useless comments. ....................................................................... 18

    Rule 5. Don‘t put huge lists of formal documentation comments on every

    declaration. ....................................................................................... 21

    Rule 6. Use thoughtful prose, not a laundry list of attributes to document

    something. ......................................................................................... 22

    Rule 7. Include project and version identification information in all shipped

    CPP and H files. ................................................................................. 23

    Rule 8. Use #if 0 to ―comment out‖ blocks of code. ......................................... 23

    Rule 9. Always use the correct instance handle when writing code for a DLL. 33

    Rule 10. Consider users that have different character sets. ............................. 42

    Rule 11. Don‘t use casts where none are needed. ............................................ 45

    Rule 12. Use dynamic_cast when downcasting. ............................................... 45

    Rule 13. Avoid preprocessor macros in favor of other language mechanisms. .. 47

    Rule 14. Avoid static constructors and destructors. ......................................... 54

    Rule 15. Qualify global const variables with static or extern. ........................... 54

    Rule 16. Use the real bool type, not a substitute. ............................................ 55

    Rule 17. Classes must contain the 4 canonical members. ............................... 61

    Rule 18. Constructors should be robust. ......................................................... 61

    Rule 19. Destructors should generally be virtual. ............................................ 61

    Rule 20. Exceptions may not escape from destructors. .................................... 62

    Rule 21. A destructor may be called at any time. ............................................. 63

    Rule 22. Extra constructors don‘t remove the requirement for a copy constructor

    to be defined. ..................................................................................... 64

    C++ Programming Guidelines Page 5

    John M. Dlugosz 18-July-1999

Introduction

    Considerations

    The fundamental goals of this design is to produce code that is robust and

    maintainable.

    Notice that readable is not listed as a primary goal. Instead, readability is merely

    one aspect of maintainability. But maintainability covers broader and deeper

    ground.

    Writing the most efficient code is not part of this document. Often the issues of being robust (e.g. checking array subscripts) and maintainable (e.g. isolating a subsystem) seem to contradict the goal of efficiency.

    In fact, such things have a linear impact on the program’s performance. By linear impact, I mean it may slow down by 20% or some such, which is a linear equation. So, don’t be penny-wise and pound-foolish. A 20% performance change is nothing in the grand scheme of things! First of all, CPU speed is doubling every few years, so you can generally assume that the specified hardware will be fast enough for the desired software. Second, linear changes are not where real performance gains come from.

    2Algorithms make or break the program’s performance. Writing a O(n) function

    where you could have used O(n log n) is a big difference. We’re talking orders of

    magnitude here, not a percentage or even a small multiplier. Writing maintainable code means that algorithms can be improved later, for bigger gain than writing slightly faster but inflexible code originally.

    Naturally, some special routines may need to be highly optimized, but that is a small part of the general development process.

    Many of the issues discussed in this document assume that the primary goal of our software is to work correctly, work reliably, and readily evolve towards future needs. Additionally, some of the issues are from the point of view of internal reusable component developers, which require more guidelines than final applications.

    C++ Programming Guidelines Page 6

    John M. Dlugosz 18-July-1999

Scope

    This tends to cover implementation architectural issues, and leans away from source code formatting. There is more universal truth to “correctness” than to

    “aesthetically pleasing”.

    One time in a code review, I found that the programmers present really didn’t care about a few formatting issues that were pointed out by QA personnel. Empirically, exact details of formatting seems to be rather unimportant. So, the exact formatting details should not be harped on by rule-strict ninnies to the same extent that a compiler complains about outright syntax errors. If the programmers can read it OK, the formatting is OK.

    More important is identifying issues in the implementation that lead to incorrect code, such as true programming rules that are not well known or considered; and standards for interoperability to promote code reuse. The compiler doesn’t catch them, but such violations should indeed be considered “wrong” in a formal sense.

    Second, maintainability issues can be things that are not “wrong”, but hurt you in the long run. Unlike the first category, such things may be deferred or ignored on a case-by-case basis.

    C++ Programming Guidelines Page 7

    John M. Dlugosz 18-July-1999

    C++ Header Files Standard Structure of a .H file

    updated 8-September-2000

    A public header file for reusable code should have this overall structure:

    ; // comment block

     #pragma once

     #if !defined unique_guard_symbol

     #define unique_guard_symbol

     #if !defined unique_export_symbol

     #define unique_export_symbol __declspec(dllimport)

     #endif

     #include "classics\exception.h"

     #define PUBLISH unique_export_symbol

     namespace xxx {

     using classics::ulong;

    ( class whatever {

    

     };

     } // end namespace xxx

     #undef PUBLISH

     #endif // include only once

1. A comment block describing the file goes at the top. See Revision Control

    Information on page 22 for more on this block comment. 2. This pragma ensures that the header file is only included a single time.

    This is seen before the common #ifdef/#define mechanism for this, and is

    superior in terms of compilation speed.

    Alternatively, use the form shown in Globally Unique Identifier Names on

    page 13 if #pragma once is known to be a problem or is not available. Or,

    both mechanisms can be present in the same file, as shown in the

    example: if #pragma once is respected and is working properly, then the

    compiler goes no farther and doesn‘t have to process the conditional

    compilation. Otherwise, the conditional compilation is used. C++ Programming Guidelines Page 8

    John M. Dlugosz 18-July-1999

    3. This mechanism is used for header files associated with DLLs, and is not

    present otherwise.

    It allows the same header file to export symbols when compiling the DLL

    itself, or import symbols when using that DLL in other code. This is

    explained in more detail elsewhere.

    The name of the symbol is unique, as defined in Globally Unique Identifier

    sample.dll in this example, each associated Names on page 13. For

    header file uses the same symbol. This mechanism is explained in more

    detail in Exporting Symbols on page 29.

    4. Include files pulled in by this include file, commonly called ―nested

    includes‖, go here. The include path should be qualified with the library

    name, even if in the same directory as this header. See Format of the

    #include statement on page 11 for more on include files.

    5. The unique identifier used in step 3 prevents clashes but is difficult to

    1use in code. So the PUBLISH symbol is defined for use only within the

    body of this header. The declarations in the header can be prefixed with

    PUBLISH to indicate that they are part of the DLLs public interface.

    It is important that the PUBLISH symbol is defined after any nested

    includes, and is undefined at the end of this file. That makes PUBLISH

    essentially local, and each header may use it for this same purpose, even

    though they belong to different DLLs.

    This cooperation breaks down if some include file uses it for some other

    2purpose, but this can be easily dealt with if the need ever arises.

    6. The body of the header is wrapped in the namespace associated with this

    library. Note that everything else goes inside this namespace. It is

    recommended that the closing brace of the namespace be commented. 7. Any using declarations or using directives go inside the namespace. You

    shouldn‘t have any, but that‘s another story (see Header Content

    Restrictions on page 9).

    8. The bulk of the header file contains declarations. This is the purpose of

    the header. Everything else is overhead which wraps this stuff.

    Rule 1. Use the standard structure for a .H file. Header Content Restrictions

    A ―component‖, meaning a reusable piece of C++ code (usually a class) is accessed by its clients by including a header file. Ideally, the header will provide access to that component alone and not have side effects. Furthermore,

1 Previous versions of this document used EXPORT instead of PUBLISH. Thanks to 杨立明

    for pointing out that EXPORT was in fact used by Microsoft‘s MAPI header, and

    suggesting PUBLISH as a suitable replacement. 2 A trivial way of dealing with it is to simply include the problematic header after any headers that use this mechanism.

    C++ Programming Guidelines Page 9

    John M. Dlugosz 18-July-1999

    use of that component should not affect the use of other components. Finally, you need to beware of proliferating or circular dependencies on libraries, especially when using DLLs.

     in a public header unless the component is Don‟t include

    tied to a particular framework.

    This Win32 system header is notorious for being unfriendly. Besides declaring thousands of functions and global identifiers for everything in Windows, it also contains several thousand macros that can cause problems with other code. This is especially true when is suddenly introduced into code that

    didn‘t use it before—many people report that unexpected macros cause major

    or subtle changes to the code.

    Other headers may conflict with either by design (because it also

    defines the same system calls or structures) or by accident, because of the rampant global name pollution. So it‘s easy for some code to be allergic to . Here is an example from Microsoft‘s own development tools:

    From Matt Pietrek, Microsoft Systems Journal Volume 12 Number 1.

    If everything I’ve described so far is correct, it should be relatively easy to construct a very small

    sample program that calls NtQueryInformationProcess and spits out the results of a query. Having

    been there and done that, I can tell you of some pitfalls that you’d encounter along the way. The

    first of these stumbling blocks is that NTDDK.H and WINDOWS.H do not get along. If you try to

    #include both WINDOWS.H and NTDDK.H in the same source file, you’ll get numerous compiler

    errors.

    The reason for the compiler errors is that many of the include files in the DDK overlap with files in

    the Win32 SDK (and by implication, the Visual C++? version of those files). These overlapping files

    (WINNT.H, for instance) aren’t identical to their SDK counterparts. I tried for quite some time to get

    some combination of DDK files and SDK files to work together, but finally gave up. Instead, I

    extracted just enough of NTDDK.H to get the necessary definitions and created the

    NTQUERYINFORMATIONPROCESS.H file. The demo program that I’ll describe later on uses

    NTQUERYINFORMATIONPROCESS.H rather than NTDDK.H.

    This report says a lot about the poor engineering of , but also tells

    us that an unrelated component would be difficult to use in a device driver if that component happened to drag in in its own header.

    Follow a set of coupling rules when permitting nested includes.

     Why…?

    Follow rules regarding using declarations, using directives, and global symbols.

     More details to follow…

    C++ Programming Guidelines Page 10

    John M. Dlugosz 18-July-1999

Report this document

For any questions or suggestions please email
cust-service@docsford.com