#C++ 注释
#概述
注释是代码中的文本说明,用于解释代码的目的、功能和实现细节。编译器会忽略注释内容,它们仅用于提高代码的可读性和可维护性。良好的注释习惯是专业编程的重要标志。
#📝 注释类型
#单行注释
#include <iostream>
int main() {
// 这是单行注释
int age = 25; // 变量声明和初始化
std::cout << "Hello World" << std::endl; // 输出语句
// 计算圆的面积
double radius = 5.0;
double area = 3.14159 * radius * radius; // 面积公式:π * r²
return 0; // 函数返回值
}#多行注释
/*
* 这是多行注释的示例
* 可以跨越多行
* 通常用于较长的说明
*/
#include <iostream>
/*
* 函数名: calculateArea
* 功能: 计算矩形面积
* 参数: length - 长度, width - 宽度
* 返回值: 矩形面积
*/
double calculateArea(double length, double width) {
/*
* 面积计算公式
* Area = Length × Width
*/
return length * width;
}
/* 主函数 */
int main() {
double length = 10.0; /* 矩形长度 */
double width = 5.0; /* 矩形宽度 */
/* 调用函数计算面积 */
double area = calculateArea(length, width);
/* 输出结果 */
std::cout << "矩形面积: " << area << std::endl;
return 0;
}#嵌套注释问题
// 注意:C++的多行注释不能嵌套
/*
* 这是外层注释
/* 这个内层注释会导致问题 */
* 因为第一个 */ 会结束整个注释块
*/
// 正确的做法是使用单行注释来"注释掉"包含多行注释的代码
// /*
// * 这样可以安全地注释掉多行注释
// * 不会产生嵌套问题
// */
// 或者使用预处理器指令
#if 0
/*
* 这块代码不会被编译
* 可以包含任何类型的注释
*/
int unused_function() {
// 这些代码都不会被编译
return 42;
}
#endif#🎨 注释风格和最佳实践
#文件头注释
/**
* @file: calculator.cpp
* @author: 张三
* @date: 2024-01-15
* @version: 1.0
* @description: 简单计算器程序,提供基本的数学运算功能
* @copyright: Copyright (c) 2024
*/
#include <iostream>
#include <cmath>
/**
* @brief 计算器类
*
* 提供基本的数学运算功能,包括加减乘除和幂运算
*/
class Calculator {
public:
/**
* @brief 加法运算
* @param a 第一个操作数
* @param b 第二个操作数
* @return 两数之和
*/
static double add(double a, double b) {
return a + b;
}
/**
* @brief 除法运算
* @param dividend 被除数
* @param divisor 除数
* @return 除法结果
* @throws std::invalid_argument 当除数为0时抛出异常
*/
static double divide(double dividend, double divisor) {
if (divisor == 0) {
throw std::invalid_argument("除数不能为零");
}
return dividend / divisor;
}
};#函数注释
#include <vector>
#include <algorithm>
/**
* @brief 在数组中查找目标值
*
* 使用线性搜索算法在数组中查找指定的目标值。
* 时间复杂度: O(n),空间复杂度: O(1)
*
* @param arr 要搜索的数组
* @param target 目标值
* @return 如果找到目标值,返回其索引;否则返回-1
*
* @example
* std::vector<int> numbers = {1, 3, 5, 7, 9};
* int index = linearSearch(numbers, 5); // 返回2
*/
int linearSearch(const std::vector<int>& arr, int target) {
// 遍历数组中的每个元素
for (size_t i = 0; i < arr.size(); ++i) {
// 如果找到目标值,返回索引
if (arr[i] == target) {
return static_cast<int>(i);
}
}
// 未找到目标值
return -1;
}
/**
* @brief 快速排序算法实现
*
* 递归实现的快速排序算法,平均时间复杂度为O(n log n)
*
* @param arr 要排序的数组(会被修改)
* @param low 排序范围的起始索引
* @param high 排序范围的结束索引
*
* @pre low >= 0 && high < arr.size()
* @post arr[low..high] 按升序排列
*/
void quickSort(std::vector<int>& arr, int low, int high) {
if (low < high) {
// 分区操作,获取基准元素的正确位置
int pivot = partition(arr, low, high);
// 递归排序基准元素左侧的元素
quickSort(arr, low, pivot - 1);
// 递归排序基准元素右侧的元素
quickSort(arr, pivot + 1, high);
}
}#类和成员注释
/**
* @brief 银行账户类
*
* 模拟银行账户的基本操作,包括存款、取款和查询余额
* 确保账户操作的安全性和数据完整性
*/
class BankAccount {
private:
std::string accountNumber_; ///< 账户号码
std::string ownerName_; ///< 账户持有人姓名
double balance_; ///< 账户余额
bool isActive_; ///< 账户是否激活
/**
* @brief 验证交易金额的有效性
* @param amount 交易金额
* @return 如果金额有效返回true,否则返回false
*/
bool isValidAmount(double amount) const {
return amount > 0 && amount <= 1000000; // 单笔交易限额100万
}
public:
/**
* @brief 构造函数
* @param accountNumber 账户号码
* @param ownerName 账户持有人姓名
* @param initialBalance 初始余额(默认为0)
*/
BankAccount(const std::string& accountNumber,
const std::string& ownerName,
double initialBalance = 0.0)
: accountNumber_(accountNumber)
, ownerName_(ownerName)
, balance_(initialBalance)
, isActive_(true) {
// 验证初始余额
if (initialBalance < 0) {
throw std::invalid_argument("初始余额不能为负数");
}
}
/**
* @brief 存款操作
*
* 向账户中存入指定金额,更新账户余额
*
* @param amount 存款金额,必须大于0
* @return 操作成功返回true,失败返回false
*
* @warning 单笔存款金额不能超过100万
*/
bool deposit(double amount) {
// 检查账户状态
if (!isActive_) {
std::cerr << "账户已冻结,无法进行存款操作" << std::endl;
return false;
}
// 验证存款金额
if (!isValidAmount(amount)) {
std::cerr << "无效的存款金额" << std::endl;
return false;
}
// 执行存款操作
balance_ += amount;
std::cout << "存款成功,当前余额: " << balance_ << std::endl;
return true;
}
/**
* @brief 取款操作
*
* @param amount 取款金额
* @return 操作成功返回true,失败返回false
*
* @note 取款金额不能超过当前余额
*/
bool withdraw(double amount) {
// 检查账户状态
if (!isActive_) {
std::cerr << "账户已冻结,无法进行取款操作" << std::endl;
return false;
}
// 验证取款金额
if (!isValidAmount(amount)) {
std::cerr << "无效的取款金额" << std::endl;
return false;
}
// 检查余额是否足够
if (amount > balance_) {
std::cerr << "余额不足,当前余额: " << balance_ << std::endl;
return false;
}
// 执行取款操作
balance_ -= amount;
std::cout << "取款成功,当前余额: " << balance_ << std::endl;
return true;
}
/**
* @brief 获取账户余额
* @return 当前账户余额
*/
double getBalance() const {
return balance_;
}
};#📋 文档生成注释 (Doxygen)
#Doxygen标签
/**
* @brief 数学工具类
* @details 提供常用的数学计算功能,包括基本运算、三角函数、对数函数等
* @author 李四
* @date 2024-01-15
* @version 2.1.0
* @since 1.0.0
* @todo 添加更多高级数学函数
* @bug 在极大数值时可能出现溢出
* @warning 某些函数可能抛出异常
*/
class MathUtils {
public:
/**
* @brief 计算两个数的最大公约数
*
* @param a 第一个整数
* @param b 第二个整数
* @return int 最大公约数
*
* @par 算法
* 使用欧几里得算法(辗转相除法)
*
* @par 示例
* @code
* int gcd = MathUtils::gcd(48, 18); // 返回6
* @endcode
*
* @see lcm()
* @since 1.0.0
*/
static int gcd(int a, int b) {
// 使用递归实现欧几里得算法
if (b == 0) {
return a;
}
return gcd(b, a % b);
}
/**
* @brief 计算两个数的最小公倍数
*
* @param a 第一个整数
* @param b 第二个整数
* @return int 最小公倍数
*
* @note 使用公式: lcm(a,b) = (a * b) / gcd(a,b)
*
* @see gcd()
* @since 1.0.0
*/
static int lcm(int a, int b) {
return (a * b) / gcd(a, b);
}
/**
* @brief 判断一个数是否为质数
*
* @param n 要检查的数
* @return true 如果是质数
* @return false 如果不是质数
*
* @par 时间复杂度
* O(√n)
*
* @par 空间复杂度
* O(1)
*
* @pre n > 0
* @post 返回值正确表示n是否为质数
*
* @exception std::invalid_argument 当n <= 0时抛出
*/
static bool isPrime(int n) {
if (n <= 0) {
throw std::invalid_argument("输入必须为正整数");
}
if (n <= 1) return false; // 0和1不是质数
if (n <= 3) return true; // 2和3是质数
if (n % 2 == 0 || n % 3 == 0) return false; // 排除2和3的倍数
// 检查5, 7, 11, 13, ...
for (int i = 5; i * i <= n; i += 6) {
if (n % i == 0 || n % (i + 2) == 0) {
return false;
}
}
return true;
}
};#条件编译注释
#include <iostream>
// 调试宏定义
#ifdef DEBUG
#define DBG_PRINT(x) std::cout << "DEBUG: " << x << std::endl
#else
#define DBG_PRINT(x) // 在非调试模式下为空
#endif
/**
* @brief 演示条件编译的使用
*/
void demonstrateConditionalCompilation() {
int value = 42;
// 调试信息只在DEBUG模式下输出
DBG_PRINT("变量value的值是: " << value);
#ifdef ENABLE_LOGGING
std::cout << "日志功能已启用" << std::endl;
#endif
#ifndef PRODUCTION_BUILD
// 仅在非生产环境下的代码
std::cout << "这是开发环境的调试代码" << std::endl;
#endif
// 平台特定代码
#ifdef _WIN32
std::cout << "运行在Windows平台" << std::endl;
#elif defined(__linux__)
std::cout << "运行在Linux平台" << std::endl;
#elif defined(__APPLE__)
std::cout << "运行在macOS平台" << std::endl;
#else
std::cout << "未知平台" << std::endl;
#endif
}#🚫 注释的常见误区
#不好的注释示例
// 不好的注释示例
// 增加i的值 ❌ 显而易见的注释
i++;
// 将x设置为0 ❌ 重复代码内容
int x = 0;
// 循环10次 ❌ 描述实现而非目的
for (int i = 0; i < 10; i++) {
// TODO: 修复这个bug ❌ 模糊的TODO
process(i);
}
/* 这个函数很重要!!! */ ❌ 情绪化的注释
int importantFunction() {
// 这里有一个hack ❌ 承认代码质量问题但不解释
return 42;
}
// 约翰写的代码,不要修改 ❌ 责任推卸
void johnsCode() {
// 一些复杂的逻辑...
}#好的注释示例
// 好的注释示例
/**
* @brief 使用二分查找算法在有序数组中查找元素
*
* 由于数组已排序,我们可以使用二分查找来提高效率
* 时间复杂度从O(n)降低到O(log n)
*/
int binarySearch(const std::vector<int>& arr, int target) {
int left = 0;
int right = arr.size() - 1;
while (left <= right) {
// 避免整数溢出的中点计算方法
int mid = left + (right - left) / 2;
if (arr[mid] == target) {
return mid;
} else if (arr[mid] < target) {
left = mid + 1; // 目标在右半部分
} else {
right = mid - 1; // 目标在左半部分
}
}
return -1; // 未找到目标元素
}
/**
* @brief 计算斐波那契数列的第n项
*
* 使用动态规划方法避免重复计算,
* 相比递归方法大大提高了效率
*/
long long fibonacci(int n) {
if (n <= 1) return n;
// 使用滚动数组优化空间复杂度
long long prev2 = 0; // f(n-2)
long long prev1 = 1; // f(n-1)
long long current = 0;
for (int i = 2; i <= n; i++) {
current = prev1 + prev2;
prev2 = prev1;
prev1 = current;
}
return current;
}
// 业务逻辑:根据用户等级计算折扣
// VIP用户享受20%折扣,普通用户享受5%折扣
double calculateDiscount(UserLevel level, double amount) {
const double VIP_DISCOUNT = 0.20;
const double REGULAR_DISCOUNT = 0.05;
switch (level) {
case UserLevel::VIP:
return amount * VIP_DISCOUNT;
case UserLevel::Regular:
return amount * REGULAR_DISCOUNT;
default:
return 0.0; // 新用户无折扣
}
}#🛠️ 注释工具和技巧
#IDE注释快捷键
// 大多数IDE的注释快捷键:
// Visual Studio / VS Code:
// Ctrl + / 单行注释/取消注释
// Ctrl + Shift + / 多行注释/取消注释
// CLion / IntelliJ:
// Ctrl + / 单行注释/取消注释
// Ctrl + Shift + / 多行注释/取消注释
// 注释模板示例
/**
* @brief ${函数功能描述}
*
* @param ${参数名} ${参数描述}
* @return ${返回值描述}
*
* @author ${作者}
* @date ${日期}
*/#注释维护建议
#include <iostream>
#include <vector>
/**
* @brief 数据处理类
* @version 2.0.0
* @changelog
* - v2.0.0: 重构了数据处理算法,提高了性能
* - v1.5.0: 添加了错误处理机制
* - v1.0.0: 初始版本
*/
class DataProcessor {
private:
std::vector<int> data_;
public:
/**
* @brief 处理数据
*
* @deprecated 此方法已弃用,请使用processDataV2()
* @see processDataV2()
*/
[[deprecated("使用processDataV2()替代")]]
void processData() {
// 旧的处理逻辑...
}
/**
* @brief 新版本的数据处理方法
*
* 相比旧版本提高了50%的性能,并增加了错误处理
*
* @since 2.0.0
*/
void processDataV2() {
// 新的优化处理逻辑...
try {
// 处理数据...
} catch (const std::exception& e) {
std::cerr << "数据处理错误: " << e.what() << std::endl;
}
}
};#总结
注释是代码文档化的重要手段,良好的注释习惯包括:
#注释原则
- 解释为什么,而不是是什么:注释应该说明代码的目的和原因
- 保持注释与代码同步:修改代码时及时更新注释
- 避免显而易见的注释:不要注释一目了然的代码
- 使用一致的风格:团队应该统一注释格式和风格
#注释类型用途
- 单行注释 (//) :简短说明、临时标记
- 多行注释 (/ /) :详细文档、大段说明
- 文档注释 :API文档、自动生成文档
#最佳实践
- 在复杂算法前添加说明
- 为公共接口编写详细文档
- 使用标准化的文档格式(如Doxygen)
- 避免注释掉的代码长期存在
良好的注释不仅帮助其他开发者理解代码,也有助于你在未来维护自己的代码。