doxygen 使用简介(C,C++为代码作注释)

 

doxygen注释块

doxygen注释块其实就是在C"C++注释块的基础添加一些额外标识, 使doxygen把它识别出来, 并将它组织到生成的文档中去。

在每个代码项中都可以有两类描述, 这两类描述将在文档中格式化在一起: 一种就是brief描述, 另一种就是detailed 两种都是可选的,但不能同时没有。

顾名思义, 简述(brief)就是在一行内简述地描述。而详细描述(detailed description)则提供更长, 更详细的文档。

doxygen, 有多种方法将注释块标识成详细描述:

1. 你可以使用JavaDoc风格, 即在C风格注释块开始使用两个星号'*', 就像这样:

2. /**
3.  * ... 描述 ...
4.  */

5. 或者你使用Qt风格代码注释, 即在C风格注释块开始处添加一个叹号'!':

6. /*!
7.  * ... 描述 ...
8.  */

注释块中间的星号是可选, 所以将注释块写成:

/*!
 ... 描述 ...
*/

同样也是有效的.

9. 第三种方法就是使用连续两个以上C++注释行所组成的注释块, 而每个注释行开始处要多写一个斜杠或写一个叹号。像下行这样:

10.                           ///
11.                           /// ... 描述 ...
12.                           ///

或者

//!
//!... 描述 ...
//!

13. 一些人喜欢使他们的注释块在文档中显得更为显目, 所以你也可以这么做:

14.                           /////////////////////////////////////////////////
15.                           /// ... 描述 ...
16.                           /////////////////////////////////////////////////

简述同样也可以同种写法:

1. 一种是在一个doxygen注释块中使用 "brief . 这个命令只对当前一个文字段有效, 所以详细描述应该与之间隔一个空行.

像这样:

/*! "brief 这里是简要描述.
 *         这里仍然是简要描述.
 *
详细描述从这里开始.
 */

2. 如果在doxygen配置文件将 JAVADOC_AUTOBRIEF设置成YES。则JavaDoc风格将注释块中的第一个句子视为简要描述, 这个句子可以以句号'.'、空格或者空行来结束:

3. /** 这里是简述, 并由句号结束. 详细描述从这里
4.  * 开始.
5.  */

这个功能同样多行C++行注释段中有效:

/// 这里是简述, 并由句号结束. 详细描述从这里
/// 开始..

6. 第三种方法就是详细描述注释段紧跟在一行C++注释段后面, 至多隔一个空行, 如下面两个例子:

7. /// 简述.
8. /** 详细描述. */

或者

//! 简述.
 
//! 详细描述
//! 从这里开始.

注意最后一个例子, 例子那个空行是用来分隔简述注释段和详细描述段的, 不能去掉.而且JAVADOC_AUTOBRIEF不应该被设置成YES.

看上去doxygen是相当富有弹性, 但下面的例子是非法的:

//! 这个简述因为是多行的
//! 会被认为是详细描述..
/*! 而这里则是另外的详细描述.
 */

因为doxygen只允许一个简要和一个详细描述。

此外, 如果在一个代码项的声明之前有简要描述而且在其定义之前也有简要描述, 那么doxygen只使用声明之前的描述。而如果详细描述出现了同样的情况, doxygen则会使用定义之前的描述, 另外的描述会被忽略掉。

这里有一个使用Qt风格的C++代码:

//! A test class. 
/*!
 A more elaborate class description.
*/
 
class Test
{
 public:
 
    //! An enum.
    /*! More detailed enum description. */
    enum TEnum { 
                 TVal1, /*!< Enum value TVal1. */ 
                 TVal2, /*!< Enum value TVal2. */ 
                 TVal3 /*!< Enum value TVal3. */ 
               } 
         //! Enum pointer.
         /*! Details. */
         *enumPtr, 
         //! Enum variable.
         /*! Details. */
         enumVar; 
    
    //! A constructor.
    /*!
      A more elaborate description of the constructor.
    */
    Test();
 
    //! A destructor.
    /*!
      A more elaborate description of the destructor.
    */
   ~Test();
    
    //! A normal member taking two arguments and returning an integer value.
    /*!
      "param a an integer argument.
      "param s a constant character pointer.
      "return The test results
      "sa Test(), ~Test(), testMeToo() and publicVar()
    */
    int testMe(int a,const char *s);
       
    //! A pure virtual member.
    /*!
      "sa testMe()
      "param c1 the first argument.
      "param c2 the second argument.
    */
    virtual void testMeToo(char c1,char c2) = 0;
   
    //! A public variable.
    /*!
      Details.
    */
    int publicVar;
       
    //! A function variable.
    /*!
      Details.
    */
    int (*handler)(int a,int b);
};
 

点击这里查看doxygen产生的HTML文档.

只有一行的注释段包含的是简述, 而多行的注释段则包含的是详细描述.

简要描述可以被用来进行classnamespace或者文件的成员描述, 被以较小的斜体字型显示出来。(这种描述可以通过将BRIEF_MEMBER_DESC设置成NO来隐藏。)默认情况下,简要描述会被显示成详细描述的第一个句子。(这同样可以通过将REPEAT_BRIEF设置成NO来屏蔽。)Qt风格中, 两种描述都是可选的。

默认情况下, JavaDoc风格的注释段和Qt风格的注释段的行为是相同的。但这样, 就不符合JavaDoc标准, 注释段的第一个句应该自动识别为简要描述。你应该设置JAVADOC_AUTOBRIEFyly YES 来启用这个功能。如果你设置了这个选项并想在句子中间放置一个句号, 你应该在后面添加一个反斜杠和一个空格. 就像下面的例子一样:

 /** Brief description (e.g." using only a few words). Details follow. */

Here is the same piece of code as shown above, this time documented using the JavaDoc style and JAVADOC_AUTOBRIEF set to YES:

/**
 * A test class. A more elaborate class description.
 */
 
class Test
{
 public:
 
    /** 
     * An enum.
     * More detailed enum description.
     */
 
    enum TEnum { 
          TVal1, /**< enum value TVal1. */ 
          TVal2, /**< enum value TVal2. */ 
          TVal3 /**< enum value TVal3. */ 
         } 
       *enumPtr, /**< enum pointer. Details. */
       enumVar; /**< enum variable. Details. */
       
      /**
       * A constructor.
       * A more elaborate description of the constructor.
       */
      Test();
 
      /**
       * A destructor.
       * A more elaborate description of the destructor.
       */
     ~Test();
    
      /**
       * a normal member taking two arguments and returning an integer value.
       * @param a an integer argument.
       * @param s a constant character pointer.
       * @see Test()
       * @see ~Test()
       * @see testMeToo()
       * @see publicVar()
       * @return The test results
       */
       int testMe(int a,const char *s);
       
      /**
       * A pure virtual member.
       * @see testMe()
       * @param c1 the first argument.
       * @param c2 the second argument.
       */
       virtual void testMeToo(char c1,char c2) = 0;
   
      /** 
       * a public variable.
       * Details.
       */
       int publicVar;
       
      /**
       * a function variable.
       * Details.
       */
       int (*handler)(int a,int b);
};
 

点击这里查看doxygen产生的HTML文档.

不像其它的文档系统 , doxygen允许在代码项的定义之前面放置成员(包括全局函数)的注释。这种方法可以在源文件中进行文档注释工作。这就是使得头文件可以比较简洁, 使代码的实现人员更容易阅读。比较折中的方案就是在声明的地方添加简要描述, 在实现的地方添加详细描述。

在成员后面放置文档

如果你想对文件、结构体、联合体、类或者枚举的成员进行文档注释的话, 并且要在成员中间添加注释, 而这些注释往往都是在每个成员后面。为此, 你可以使用在注释段中使用'<'标识

Here are some examples:

int var; /*!< Detailed description after the member */

This block can be used to put a Qt style detailed documentation block after a member. Other ways to do the same are:

int var; /**< Detailed description after the member */

或者

int var; //!< Detailed description after the member
         //! 

或者

int var; ///< Detailed description after the member
         /// 

Most often one only wants to put a brief description after a member. This is done as follows:

int var; //!< Brief description after the member

或者

int var; ///< Brief description after the member

Note that these blocks have the same structure and meaning as the special comment blocks in the previous section only the < indicates that the member is located in front of the block instead of after the block.

Here is an example of the use of these comment blocks:

/*! A test class */
 
class Test
{
 public:
    /** An enum type. 
     * The documentation block cannot be put after the enum! 
     */
    enum EnumType
    {
      int EVal1,     /**< enum value 1 */
      int EVal2      /**< enum value 2 */
    };
    void member();   //!< a member function.
    
  protected:
    int value;       /*!< an integer value */
};

点击这里查看doxygen产生的HTML文档.

警告:

这种注释方法只能在成员参数中使用。它们不能用在描述文件、类、联合体、名字空间和枚举本身。此外, 在下一节提到的结构化命令("class)在这种注释段中是无效的。

在其它地方进行注释

虽然我们一般是在声明和定义的前面添加文档注释块, 但也许出于某种情况需要将文档放在其它什么位置上。比如我们需要编写一段实际上不存在的文件的描述。因此, Doxygen允许将文档放置在任何位置。(除了在函数体内或在一个普通的注释段)

为了达到这种目的, 你唯一要做的就是在注释段中使用结构化命令。

结构化命令(就像其它命令)由一个反斜杠("), JavaDoc风格中使用的@来做开头, 后面紧跟着命令名字和一些参数。例如, 你想注释一个名为Test的类, 如下例:

/*! "class Test
    "brief A test class.
 
    A more detailed class description.
*/

命令"class被用来指示代码段中包含着关于Test类的文档.其它的结构化命令有:

·"struct 生成 C结构的文档.

·"union 生成联合体的文档.

·"enum 生成枚举的文档.

·"fn 生成函数的文档.

·"var生成变量或typedef或枚举值的文档.

·"def 生成#define定义的文档.

·"file 生成关于一个文件的文档.

·"namespace 生成名字空间的文档.

·"package 生成Java包的文档.

·"interface 生成IDL接口的文档.

参看特殊命令得到更多关于这些命令或其它命令的详细信息.

C++类的成员进行文档注释时, 必须对类本身进行文档注释。这同样对名字空间有效。要对全局函数、typedef、枚举或宏定义进行文档注释, 则必须先对包含它们的文件进行文档(这通常是头文件).

再重复一下, 因为它经常被忘记: 如果要对全局项目(:函数、typedefs、枚举或宏等), 你必须必须对定义它们的文件进行文档注释。换一句话, 你至少在文件写下

 /*! "file */ 

 /** @file */ 

这样的注释.

下面是一个名为structcmd.h头文件的例子, 里面包含了使用结构化命令的例子:

/*! "file structcmd.h
    "brief A Documented file.
    
    Details.
*/
 
/*! "def MAX(a,b)
    "brief A macro that returns the maximum of "a a and "a b.
   
    Details.
*/
 
/*! "var typedef unsigned int UINT32
    "brief A type definition for a .
    
    Details.
*/
 
/*! "var int errno
    "brief Contains the last error code.
 
    "warning Not thread safe!
*/
 
/*! "fn int open(const char *pathname,int flags)
    "brief Opens a file descriptor.
 
    "param pathname The name of the descriptor.
    "param flags Opening flags.
*/
 
/*! "fn int close(int fd)
    "brief Closes the file descriptor "a fd.
    "param fd The descriptor to close.
*/
 
/*! "fn size_t write(int fd,const char *buf, size_t count)
    "brief Writes "a count bytes from "a buf to the filedescriptor "a fd.
    "param fd The descriptor to write to.
    "param buf The data buffer to write.
    "param count The number of bytes to write.
*/
 
/*! "fn int read(int fd,char *buf,size_t count)
    "brief Read bytes from a file descriptor.
    "param fd The descriptor to read from.
    "param buf The buffer to read into.
    "param count The number of bytes to read.
*/
 
#define MAX(a,b) (((a)>(b))?(a):(b))
typedef unsigned int UINT32;
int errno;
int open(const char *,int);
int close(int);
size_t write(int,const char *, size_t);
int read(int,char *,size_t);

点击这里查看doxygen产生的HTML文档.

因为例子中的每个注释都包含了结构化命令, 所以所有的注释块都可以移动到其它的地方, 而不会对生成的文档产生影响。这种方法的坏处是当原型发生了改变 , 你不得不改变结构化命令的参数。因此, 在使用它们之前, 应该认真考虑一下是否真正需要使用它们。

 

posted @ 2008-07-24 11:07  wishma  阅读(28319)  评论(3编辑  收藏  举报