代码注释你写对了吗? Doxygen 风格注释,一目了然!

前言 

上期,咱们写了一个 史上最强C语言屎山代码之Hello World炸裂版 让人看着就懵逼,你想过为什么看不懂吗?

因为:没有注释,代码没按规范写

这期,咱就来聊聊C/C++中写代码时的注释规范

由请咱们的Doxygen登场!

一、什么是Doxygen

Doxygen风格代码注释是一种标准化的注释格式,用于生成清晰、结构化的代码文档,广泛支持 C/C++ 等语言,且能被 Visual Studio 2022 等工具识别和解析。其核心特点是通过特定标签(以 @ 或 \ 开头)描述代码元素的功能、参数、返回值等信息,便于自动生成 HTML、PDF 等格式的文档,同时提升代码可读性。

二、Doxygen注释标签

1. 文档结构标签

标签说明
@file指定文件归属与描述
@brief简要描述(显示在摘要中)
@details详细描述(可选)
@author标注作者
@date标注日期
@version指定版本号
@copyright版权声明
@mainpage定义主页面内容
@page创建独立页面
@section定义章节
@ingroup将元素归入功能组
@defgroup创建功能组

2. 函数与方法标签

标签说明
@param [in]输入参数说明
@param [out]输出参数说明
@return返回值说明
@retval特定返回值说明(多个值)
@throws异常说明(C++)
@pre前置条件
@post后置条件
@warning警告信息
@note补充说明
@deprecated标记为弃用

3. 类与结构体标签

标签说明
@class类说明
@struct结构体说明
@enum枚举说明
@extends继承关系说明
@implements实现接口说明
@interface标记为接口
@final标记为不可继承
@threadsafe线程安全说明

4. 模板与泛型标签

标签说明
@tparam模板参数说明

5. 格式化与特殊内容标签

标签说明
@code插入代码块
@example引用示例文件
@image插入图片
@dot插入 DOT 图形(流程图)
@formula插入数学公式
@note创建注意事项框
@warning创建警告框

6. 交叉引用标签

标签说明
@see参见其他元素
@sa同上(更简洁)
@ref创建内部链接
@link带文本的链接

7. 语言特定标签

标签说明
@namespace命名空间说明(C++)
@var变量 / 全局变量说明
@typedef类型定义说明

8. 其他杂项标签

标签说明
@todo待办事项
@bug已知问题
@cond条件编译控制
@if条件判断
@image插入图片
@test测试用例说明

使用提示

  • 标签前缀:可使用 @ 或 \(如 @param 与 \param 等价)。
  • 多行注释:使用 /** ... */ 包裹。
  • 单行注释:使用 /// 或 //!
  • 右侧注释:使用 ///< 或 //!<(如变量注释)。

三、如何使用Doxygen代码注释

1. 文件头部注释

必选内容:版权声明、文件功能、命名空间、依赖关系。

/**
 * @file: network/tcp_client.h
 * @brief: TCP客户端实现,基于Boost.Asio
 * @namespace: net::tcp
 * @copyright: Copyright (c) 2023 CompanyName
 * @note: 依赖 boost/asio.hpp 和 error/error_code.h
 * 
 * @authors: 王五(架构)、赵六(实现)
 * @date: 2023-05-20
 * @version: 3.0
 */

2. 类注释

必选要素:设计意图、生命周期管理、线程安全性、使用模式。
示例

/**
 * 线程安全的TCP客户端
 * 
 * @note 采用RAII模式管理连接,析构时自动关闭
 * @warning 非拷贝构造,不可复制
 * 
 * 使用示例:
 * try {
 *     TcpClient client("127.0.0.1", 8080);
 *     client.connect();
 *     client.send("Hello");
 * } catch (const std::exception& e) {
 *     // 处理异常
 * }
 */
class TcpClient final : public NetworkClient {
public:
    TcpClient(const std::string& host, uint16_t port);
    ~TcpClient() override;
    
    // 禁用拷贝构造和赋值
    TcpClient(const TcpClient&) = delete;
    TcpClient& operator=(const TcpClient&) = delete;
    
    // ...
};

3. 函数 / 方法注释

必选要素:功能描述、参数约束、返回值语义、异常规格、前置 / 后置条件。
示例

/**
 * 异步发送数据
 * 
 * @param [in] data 待发送的数据缓冲区,不可为空
 * @param [in] size 数据大小(字节)
 * @param [in] callback 完成回调函数,可空
 * 
 * @pre 已调用connect()且连接成功
 * @post 数据将加入发送队列,由IO线程处理
 * @throws NetworkException 若连接已断开
 * 
 * @example
 * client.async_send(buffer, size, [](bool success) {
 *     if (success) cout << "发送成功";
 * });
 */
void async_send(const char* data, size_t size, 
                std::function<void(bool success)> callback = nullptr);

4. 模板注释

重点说明:类型参数约束、特化场景、性能特性。
示例

/**
 * 固定大小的线程安全对象池
 * 
 * @tparam T 对象类型,必须有默认构造函数
 * @tparam Alloc 分配器类型,默认std::allocator
 * 
 * @note 预分配N个对象,避免运行时动态分配
 * @warning T类型析构函数不应抛出异常
 */
template <typename T, typename Alloc = std::allocator<T>>
class ObjectPool final {
public:
    explicit ObjectPool(size_t capacity);
    // ...
};

5. 行级注释

重点标注

  • RAII 资源管理(如智能指针、锁)。
  • 模板元编程和复杂类型推导。
  • STL 算法和自定义比较器。

// 使用RAII锁保护共享资源
{
    std::lock_guard<std::mutex> lock(mutex_); // 自动释放锁
    data_.push_back(std::move(item));
}

// 模板元编程:计算编译时常量
template <int N>
struct Factorial {
    static constexpr int value = N * Factorial<N-1>::value; // 递归展开
};
template <>
struct Factorial<0> { static constexpr int value = 1; }; // 特化终止条件

// 使用自定义比较器的优先队列
auto cmp = [](const Task& a, const Task& b) { return a.priority() < b.priority(); };
std::priority_queue<Task, std::vector<Task>, decltype(cmp)> task_queue(cmp);

6. 特殊场景注释

6.1 Lambda 表达式
// 捕获this的lambda:注意生命周期管理
auto worker = [this]() {
    while (running_) {
        process_task();
    }
};

// 移动捕获unique_ptr
auto task = std::make_unique<Task>();
queue_.push([task = std::move(task)]() {
    task->execute();
});
6.2 异常安全

/**
 * 强异常安全的交换函数
 * @throws 无(不抛出异常)
 */
void swap(MyClass& other) noexcept {
    using std::swap;
    swap(data_, other.data_); // 调用ADL查找最佳swap实现
}
6.3 性能关键代码

// 使用emplace_back避免临时对象拷贝
for (const auto& item : source) {
    target.emplace_back(std::move(item)); // 直接构造对象
}

// 性能优化:展开循环减少分支预测错误
for (int i = 0; i < 4; ++i) { // 假设已知数组大小为4
    result[i] = data[i] * scale;
}

7. 注释风格约定

  • Doxygen 风格(推荐):

    /**
     * 多行注释
     * @param ...
     */
    
  • 单行注释// 简短说明
  • 文件包含顺序

    // 本模块头文件
    #include "my_class.h"
    
    // 系统头文件
    #include <iostream>
    
    // 第三方库头文件
    #include <boost/asio.hpp>
    
    // 项目内其他模块头文件
    #include "utils/log.h"
    

8. 注释禁忌

  • 重复 obvious 代码
    // 将x加1
    ++x;  // 错误!
    
  • 忽略重要细节
    // 处理请求
    void process_request(Request& req);  // 错误!未说明线程安全和异常情况
    
  • 使用模糊术语
    // 修复了一个问题
    // 错误!应说明具体问题(如:修复了大数据量下的内存泄漏)
    

9. C++ 特殊注意事项

  1. 智能指针:标注所有权语义(如 @param [in] ptr 转移所有权的unique_ptr)。
  2. 线程安全:明确标注函数是否线程安全(如 @threadsafe 或 @not_threadsafe)。
  3. 模板特化:说明特化场景(如 @note 针对std::string的特化版本优化了内存分配)。
  4. 移动语义:标注参数是否会被移动(如 @param [in,out] data 内容将被移动)。

工具链支持

  • 文档生成:Doxygen、Sphinx(结合 Breathe)。
  • 静态分析:Clang-Tidy(检查注释与代码一致性)、CppCheck。
  • 格式化:clang-format(统一注释格式)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值