Programming °æ (¾«»ªÇø)

·¢ÐÅÈË: netiscpu (˵²»Èç×ö), ÐÅÇø: Programming
±ê  Ìâ: C++ ±à³Ì×¼ÔòÓëÖÒ¸æ Ö® Source Code in Files
·¢ÐÅÕ¾: ×Ï ¶¡ Ïã (Sun Jul 26 11:11:56 1998), ×ªÐÅ




4 Source Code in Files 

Back to index 

4.1 Structure of Code 

Back to index 

Rule 1 Include files in C++ always have the file name extension
".hh". 


Rule 2 Implementation files in C++ always have the file name
extension ".cc". 


Rule 3 Inline definition files always have the file name extension
".icc". 


Rec. 3 An include file should not contain more than one class
definition. 


Rec. 4 Divide up the definitions of member functions or functions
into as many files as possible. 


Rec. 5 Place machine-dependent code in a special file so that it may
be easily located when porting code from one machine to another. 


The purpose of these conventions is to provide a uniform
interpretation of file names. One reason for this is that it is easier
to make tools which base their behaviour on the file name extension. 

There are two kinds of include files in C++: 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 unpleasant
compilation errors (from using the wrong kind of include file). 

If a ".cc" file contains a large number of function definitions, the
object file produced by the compiler may be unnecessarily large. In
order to obtain the smallest possible executable files, it is
necessary to have a separate file for each function definition. This
is because the standard UNIX linker ld links all functions in an
object file even if only one of them is actually used. It is
especially important to remember that virtual functions are always
linked. On the other hand, there are problems in managing a large
number of files, since sufficiently powerful tools are not currently
available. Also, the time necessary to compile a program consisting of
a large number of files is longer. 

Some debuggers cannot debug inline functions. By placing inline
functions in a separate file and by including that file in the
implementation file, thus treating the inline functions as ordinary
functions, it is possible to debug the functions while testing the
program. For this to work some special preprocessor techniques must be
used. The inline definition file must not be included by the include
file for the class and the keyword `inline' must be removed. 

When tools for managing C++ code are not available, it is much easier
for those who use and maintain classes if there is only one class
definition in each file and if implementations of member functions in
different classes are not present in the same file. 



Exception to Rule 1: Include files which contain code that is accepted
by both C and C++ compilers should have the file name extension ".h". 


Exception to Rule 2: When using a compiler that does not accept the
extension ".cc", the extension ".C" is used instead. 


Exception to Rule 3: No exceptions. 



Example 1 Inline definitions in a separate file for conditional
compilation 

  // AnyClass.hh

  #ifndef OUTLINE

  #include "AnyClass.icc"

  #endif

        

  //AnyClass.cc

  #ifdef OUTLINE

  #define inline

  #include "AnyClass.icc"

  #undef inline

  #endif

        


4.2 Naming Files 

Back to index 

Rec. 6 Always give a file a name that is unique in as large a context
as possible. 


Rec. 7 An include file for a class should have a file name of the
form + extension. Use uppercase and lowercase letters in the same way
as in the source code. 


There is always a risk for name collisions when the file name is part
of identifier names that are generated by the compiler. This is a
problem in using any Cfront-based compiler. 

AT&T's Cfront-based compiler creates two functions for every file in
order to call constructors and destructors of static objects in the
proper order. These functions are named: 

char __sti__file_cc___Fv(); //filename is file.cc 
char __std__file_cc___Fv(); //filename is file.cc 
It is easily understood that if a program has two files with the same
name but in different subdirectories, there will be name collisions
between the functions generated above. 

Since class names must generally be unique within a large context, it
is appropriate to utilize this characteristic when naming its include
file. This convention makes it easy to locate a class definition using
a file-based tool. 


4.3 Comments

Back to index 


Rule 4 Every file that contains source code must be documented with
an introductory comment that provides information on the file name and
its contents. 


Rule 5 All files must include copyright information. 


Rule 6 All comments are to be written in English. 


Rec. 8 Write some descriptive comments before every function. 


Rec. 9 Use // for comments. 


It is necessary to document source code. This should be compact and
easy to find. By properly choosing names for variables, functions and
classes and by properly structuring the code, there is less need for
comments within the code. 

Note that comments in include files are meant for the users of
classes, while comments in implementation files are meant for those
who maintain the classes. 

All our code must be copyright marked. If the code has been developed
over a period of years, each year must be stated. 

The standardization of comments makes it possible to automatically
generate man-pages from source code. This may be used to keep source
code and documentation together until adequate tools for information
management are available. 

Comments are often said to be either strategic or tactical. 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. 

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 /* */. 



Exception to Rule 4: No exceptions. 


Exception to Rule 5: No exceptions. 


Exception to Rule 6: No exceptions. 



Example 2 Documentation of a file 

  //

  //  File:   test.cc

  //  Description: This is a test program

  //  Rev:   A

  //  Created:   Thur. Oct 31, 1991, 12:30:14

  //  Author:   Erik Nyquist

  //  mail:   erik.nyquist@eua.ericsson.se

  //

  //  Copyright Ellemtel Utvecklings AB 1991

  //  BOX 1505

  //  125 25 ALVSJO

  //  SWEDEN

  //  tel int + 46 8 727 3000

  //

  //  The copyright to the computer program(s) herein

  //  is the property of Ellemtel Utvecklings AB, Sweden.

  //  The program(s) may be used and/or copied  only with

  //  the written permission of  Ellemtel Utvecklings AB

  //  or in accordance   with the terms and conditions

  //  stipulated   in the agreement/contract under which

  //  the  program(s) have been supplied.

  //

        



Example 3 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;

  }

        


4.4 Include Files 

Back to index 

Rule 7 Every include file must contain a mechanism that prevents
multiple inclusions of the file. 


Rule 8 When the following kinds of definitions are used (in
implementation files or in 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, 
·  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 9 Definitions of classes that are only accessed via pointers (*)
or references (&) shall not be included as include files. 


Rule 10 Never specify relative UNIX names in #include directives. 


Rule 11 Every implementation file is to include the relevant files
that contain: 

·  declarations of types and functions used in the functions that are
implemented in the file. 

·  declarations of variables and member functions used in the
functions that are implemented in the file. 


Rec. 10 Use the directive #include "filename.hh" for user-prepared
include files. 


Rec. 11 Use the directive #include for include files from libraries. 


Rec. 12 Every implementation file should declare a local constant
string that describes the file so the UNIX command what can be used to
obtain information on the file revision. 


Rec. 13 Never include other files in an ".icc" file. 


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. 

The number of files included should be minimized. If a file is
included in an include file, then every implementation file that
includes the second include file must be re-compiled whenever the
first file is modified. A simple modification in one include file can
make it necessary to re-compile a large number of files. 

When only referring to pointers or references to types defined in a
file, it is often not necessary to include that file. It may suffice
to use a forward declaration to inform the compiler that the class
exists. Another alternative is to precede each declaration of a
pointer to the class with the keyword class. 

True portable code is independent of the underlying operating system.
For this reason, relative UNIX search paths should be avoided when
including files. The processing of such search paths depends on the
compiler and UNIX should not be taken for granted. Instead, search
paths should be provided in `make' files as options for the compiler. 

If a file only contains information that is only needed in an
implementation file, that file should not be included in another
include file. Otherwise, when the information is no longer needed in
the implementation file, it may be necessary to re-compile each file
that uses the interface defined in the include file. 

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. 

By declaring a local constant string, the compiler becomes
self-identifying. This may be used to easily determine the version of
the program that is used. The string must begin with the characters
@(#) to be read by the UNIX what command. 



Exception to Rule 7: No exceptions. 


Exception to Rule 8: No exceptions. 


Exception to Rule 9: No exceptions. 


Exception to Rule 10: No exceptions. 


Exception to Rule 11: No exceptions. 



Example 4 Technique for preventing multiple inclusion of an include
file 

  #ifndef FOO_HH

  #define FOO_HH

        

  // The rest of the file

        

  #endif

        



Example 5 Never use explicit UNIX path names 

  // NOT RECOMMENDED

  #include <../include/fnutt.h>

        

  // NOT GUARANTEED TO WORK

  #include 

        



Example 6 Local constant string for identifying implementation files.

  static const char* sccsid = 

  "@(#) Exception.cc, rev. A, Copyright Ellemtel Utvecklings AB 1991";

        



Example 7 Include file for the class PackableString 

  // file: PackableString.hh

  #ifndef PACKABLESTRING_HH

  #define PACKABLESTRING_HH



  #include "String.hh"

  #include "Packable.hh"

        

  // It is not necessary to extern-declare class Buffer when

  // each pointer declaration specifies the keyword class as shown below.

  // An explicit extern-declaration makes the code easier to 

  // understand.

        

  extern class Buffer;

        

  class PackableString : public String, public Packable

  {

    public:

      PackableString( const String& s );

      class Buffer* put( class Buffer* outbuffer );

      // ...

  };

        

  #endif

        



Example 8 Implementation file for the class PackableString 

  // PackableString.cc

        

  #include "PackableString.hh"

        

  // To be able to use Buffer-instances, Buffer.hh MUST be included.

        

  #include "Buffer.hh"

        

  Buffer*           

  PackableString::put( Buffer* outbuffer )

  {

    // ...

  }

        


--

                              Enjoy Linux!
                          -----It's FREE!-----

¡ù À´Ô´:£®×Ï ¶¡ Ïã bbs.hit.edu.cn£®[FROM: mtlab.hit.edu.cn]
[°Ù±¦Ïä] [·µ»ØÊ×Ò³] [Éϼ¶Ä¿Â¼] [¸ùĿ¼] [·µ»Ø¶¥²¿] [Ë¢ÐÂ] [·µ»Ø]
Powered by KBS BBS 2.0 (http://dev.kcn.cn)
Ò³ÃæÖ´ÐÐʱ¼ä£º212.436ºÁÃë