C++ 接口设计 && Doxygen 注释

一、接口设计速查表(核心规则)

一个"工业级"的接口,通常要同时满足这 6 点:

  1. 语义清晰:一眼能看懂函数做什么
  2. 边界明确:输入、输出、失败条件清楚
  3. 易于调用:调用者不容易用错
  4. 易于维护:后续加功能不容易破坏旧逻辑
  5. 便于文档化:注释可自动生成接口文档
  6. 便于排错:失败原因、约束条件、数据单位明确

原则

  • 函数职责越单一,越容易测试和复用
  • 名字应该准确反映行为
维度 推荐做法 不推荐做法 说明
函数职责 一个函数只做一件事 一个函数做多步逻辑 提高可维护性
函数命名 动词 + 对象(readXxx / calcXxx 模糊命名(process / handle 语义清晰
输入参数 const T& T*(无必要) 避免拷贝 + 防误用
输出参数 T& 或返回结构体 多个 T* 提高可读性
返回值 bool / enum / struct 不明确的 int 表达状态
多参数 使用 struct 封装 参数列表过长 防止顺序错误
布尔参数 enum / 配置 struct 多个 bool 可读性差
所有权 unique_ptr / shared_ptr 裸指针返回 防内存问题
参数顺序 输入 → 配置 → 输出 混乱顺序 调用更直观
接口风格 const 函数尽量加 const 忽略 const 明确不修改

1)避免不必要的裸指针

优先顺序

  • 只读输入:const T&
  • 可修改输入/输出:T&
  • 可空、可选对象:const T*T*
  • 资源所有权转移:智能指针

**建议:**如果参数理论上"不应该为空",不要用裸指针。

例如:

cpp 复制代码
bool process(const Image& img); // 更好
bool process(const Image* img); // 除非允许 nullptr

2)明确"所有权"和"生命周期"

如果接口返回指针,一定要明确:

  • 谁负责释放
  • 返回对象能活多久
  • 是否共享

不推荐:

cpp 复制代码
Image* createImage();

调用者会问:

  • 要不要 delete
  • 什么时候释放?
  • 是否会泄漏?

推荐:

cpp 复制代码
std::unique_ptr<Image> createImage();
std::shared_ptr<Image> loadSharedImage(const std::string& path);

二、参数设计速查表

参数设计常见顺序:1、核心输入;2、配置参数;3、输出参数;4、可选参数

类型 推荐写法 含义
只读输入 const T& 不修改,避免拷贝
输出参数 T& 明确输出
可选参数 const T* 允许 nullptr
大对象 const std::vector<T>& 避免拷贝
简单类型 int / double 直接传值
所有权转移 std::unique_ptr<T> 明确 ownership

三、返回值设计速查表

场景 推荐方式 示例
单一结果 直接返回 int getWidth()
成功/失败 bool + 输出参数 bool calc(...)
多结果 struct ShiftResult
多错误类型 enum Status
严重错误 exception throw

1)输入参数与输出参数要分清

推荐优先级通常是:

第一优先:直接返回结果

适合"只有一个主要结果"的函数。

cpp 复制代码
std::string readFileText(const std::string& path);

第二优先:返回状态,输出参数带结果

适合"可能失败 + 有多个输出"的函数。

cpp 复制代码
bool calcShift(const cv::Mat& a, const cv::Mat& b, double& dx, double& dy);

第三优先:返回结构体

适合"结果项较多"的函数。

cpp 复制代码
struct ShiftResult {
    bool success = false;
    double dx = 0.0;
    double dy = 0.0;
    double score = 0.0;
};

ShiftResult calcShift(const cv::Mat& a, const cv::Mat& b);

工业实践里,返回结构体 往往比多个输出参数更清晰。

2)布尔参数要慎用

不推荐:

cpp 复制代码
processImage(img, true, false, true);

根本看不出每个 true/false 什么意思。

推荐方案 1:枚举

cpp 复制代码
enum class Type {
    AAA,
    BBB,
    CCC
};

推荐方案 2:配置结构体

cpp 复制代码
struct ProcessOptions {
    bool enableFilter = true;
    bool enableDebug = false;
    bool useabc = false;
};

3)多个相关参数用结构体封装

不推荐:

cpp 复制代码
bool createROI(int x, int y, int w, int h, int searchRange, double threshold);

推荐:

cpp 复制代码
struct Param {
    int x = 0;
    int y = 0;
    int width = 0;
    int height = 0;
    int searchRange = 0;
    double threshold = 0.0;
};

bool createROI(const Param& roi);

优点:

  • 参数语义集中
  • 易扩展
  • 不容易传错顺序

4)错误处理方式要统一

常见有三类:

方式 A:返回 bool

适合简单成功/失败

cpp 复制代码
bool parseConfig(const std::string& path);

方式 B:返回错误码

适合要区分失败原因

cpp 复制代码
enum class Status {
    Ok,
    FileNotFound,
    InvalidFormat,
    OutOfRange
};

Status parseConfig(const std::string& path);

方式 C:异常

适合库式设计或严重错误

cpp 复制代码
Recipe loadRecipe(const std::string& path); // 失败抛异常

四、命名规范速查表

1)函数命名

类型 示例
读取 readXXX
加载 loadXXX
解析 parseXXX
计算 calcXXX
获取 getXXX
设置 setXXX
创建 creatXXX
更新 updateXXX
保存 saveXXX
判断 isValid / hasData

2)布尔命名

推荐 不推荐
isXXX flag
hasXXX state
canXXX enable
ShouldXXX

五、Doxygen 注释标签速查表

标签 作用 示例
@brief 一句话描述 @brief Calculate shift
@param 参数说明 @param img input image
@return 返回值 @return true if success
@retval 分情况返回 @retval true success 适合枚举或布尔返回值
@note 补充说明 @note image must be grayscale
@warning 风险提示 @warning unstable for noise
@pre 前置条件 @pre img not empty
@post 后置条件 @post result updated
@see 相关接口 @see calcShift
@todo 待做 @todo optimize speed
@author 作者 @author yanlairuci
@date 日期 @date 20260402

Doxygen 工具可以解析这些标签,自动生成:

  • HTML 文档
  • PDF 文档
  • 类图 / 调用关系图

六、Doxygen 注释结构模板

接口声明要暴露"必须知道的事"

至少说明:

  • 这个函数做什么
  • 参数含义
  • 参数单位
  • 输出含义
  • 返回值含义
  • 失败条件
  • 特殊约束

标准模板(推荐)

cpp 复制代码
/**
* @brief 简要描述(1句话)
*
* 可选:详细说明(算法/行为)
*
* @param xxx 参数说明(单位 / 范围 / 输入输出)
* @param yyy 参数说明
* @return 返回值说明
*
* @pre 前置条件
* @note 补充说明
* @warning 注意事项
*/

七、@param 写法规范

参数注释建议包含这几类信息:

  • 参数是什么
  • 输入还是输出
  • 数据类型要求
  • 单位
  • 取值范围
  • 方向含义
要素 示例
输入/输出 Input image / Output shift
单位 pixels
范围 [0,1]
方向 positive means right
约束 must be non-empty

示例(推荐写法)

cpp 复制代码
@param colShift Output horizontal shift in pixels. Positive means right.

八、@return 写法规范

如果返回 bool,不要只写 "true or false"。

如果返回容器,也要说明 key/value 语义。

类型 推荐写法
bool true if success, false otherwise
map key = id, value = info
struct contains shift and score

示例

cpp 复制代码
@return A map where key is polygon ID and value is shape info.

九、常见错误速查

错误 说明
process() 名字太泛
flag 无语义
多个 bool 可读性差
参数过多 易错
注释重复代码 没价值
返回 int 表示错误 不直观

十、最佳实践总结(最重要)

👉 接口设计 3 原则:

  1. 签名自解释(最重要)
  2. 参数语义清晰
  3. 错误行为明确

👉 注释设计 3 原则:

  1. 不重复代码
  2. 说明约束(尺寸 / 类型 / 单位)
  3. 写调用者关心的内容

一句话终极总结

👉 好接口 = 不看注释也能大致用对

👉 好注释 = 防止用错 + 解释边界条件


接口设计规范

  1. 函数名用明确动词,表达单一职责
  2. 能不用裸指针,就不用裸指针
  3. 输入参数优先 const T&
  4. 输出结果少时可用引用,多时用结构体
  5. 错误处理方式在同一模块内统一
  6. 参数顺序统一:输入 → 配置 → 输出
  7. 多个相关参数封装成结构体
  8. 布尔参数尽量少,用枚举或配置结构体替代

Doxygen 注释规范

  1. 每个对外接口都写 @brief
  2. 每个非显然参数都写 @param
  3. 每个返回值都写 @return@retval
  4. 参数说明写清楚方向、单位、范围、约束
  5. 必要时写 @pre@note@warning
  6. 注释描述"怎么用"和"边界条件",不是重复函数名
  7. 注释放在声明上方,保证生成文档时最清晰
相关推荐
野槐3 小时前
Electron开发
前端·javascript·electron
#做一个清醒的人3 小时前
【Electron】开发两年Electron项目评估报告
前端·electron
lizhongxuan9 小时前
Claude Code 防上下文爆炸:源码级深度解析
前端·后端
天真萌泪10 小时前
JS逆向自用
开发语言·javascript·ecmascript
柳杉10 小时前
震惊!字符串还能这么玩!
前端·javascript
是上好佳佳佳呀11 小时前
【前端(五)】CSS 知识梳理:浮动与定位
前端·css
仍然.11 小时前
算法题目---模拟
java·javascript·算法
wefly201711 小时前
纯前端架构深度解析:jsontop.cn,JSON 格式化与全栈开发效率平台
java·前端·python·架构·正则表达式·json·php
史蒂芬_丁12 小时前
Qt, C++数据类型扩展问题
数据库·c++·qt