# Qt C++代码规范

## 1. 文件结构和命名规范

### 1.1 头文件 (.h)

```cpp
#ifndef CLASSNAME_H    // 头文件保护符，使用全大写
#define CLASSNAME_H

// 系统头文件在前
#include <QtCore>
#include <QWidget>
#include <QSqlDatabase>

// 第三方库头文件
#include <SomeLibrary>

// 项目内部头文件在后
#include "CustomClass.h"

// 前置声明
class QTimer;

/**
 * @class ClassName
 * @brief 类的简要描述
 * 
 * 详细描述类的功能和用途
 */
class ClassName : public QWidget
{
    Q_OBJECT    // Qt元对象系统宏，必须位于类声明开始处

public:
    explicit ClassName(QWidget *parent = nullptr);
    ~ClassName();
    
    // 公有接口
    
signals:
    // 信号声明
    
public slots:
    // 公有槽函数
    
private slots:
    // 私有槽函数
    
private:
    // 私有成员变量
    // 私有成员函数
};

#endif // CLASSNAME_H
```

### 1.2 源文件 (.cpp)

```cpp
#include "ClassName.h"

// Qt头文件
#include <QDebug>
#include <QMessageBox>

// 标准库头文件
#include <algorithm>

// 构造函数实现
ClassName::ClassName(QWidget *parent)
    : QWidget(parent)  // 初始化列表
    , m_memberVariable(0)  // 成员变量初始化
{
    // 构造函数体
    setupUi();
    connectSignals();
}

ClassName::~ClassName()
{
    // 析构函数体
}
```

## 2. 命名规范

### 2.1 类名
- 使用帕斯卡命名法（PascalCase）
- 每个单词首字母大写
- 名称应该清晰地表达类的功能

**正确示例：**
```cpp
class DatabaseManager;
class InjuryAnalysisUI;
class GuidingUI;
class UserLoginDialog;
```

**错误示例：**
```cpp
class dbManager;        // 首字母应大写
class injuryanalysisui; // 单词间应区分
class UI_Login;         // 避免下划线
```

### 2.2 函数名
- 使用驼峰命名法（camelCase）
- 第一个单词小写，后续单词首字母大写
- 动词开头，清晰表达函数功能

**正确示例：**
```cpp
void addMarker();
void updateChart();
bool connectToDatabase();
QString getUserName() const;
void setUserName(const QString &name);
```

### 2.3 变量名

#### 成员变量
- 使用`m_`前缀
- 后续使用驼峰命名法

```cpp
class MyClass 
{
private:
    QString m_databaseName;     // 数据库名称
    QSqlDatabase m_sqlDb;       // 数据库连接
    int m_fieldCount;           // 字段数量
    bool m_isConnected;         // 连接状态
};
```

#### 局部变量
- 使用驼峰命名法
- 名称应该具有描述性

```cpp
void processData()
{
    QString userName;           // 用户名
    int itemCount = 0;          // 项目数量
    bool isConnected = false;   // 连接状态
    QStringList fieldNames;     // 字段名列表
}
```

#### 常量
- 全大写，下划线分隔
- 使用`const`或`constexpr`

```cpp
const int MAX_RETRY_COUNT = 3;
const QString DEFAULT_HOST = "localhost";
const double PI = 3.14159265359;
static constexpr int BUFFER_SIZE = 1024;
```

### 2.4 枚举
```cpp
enum class ConnectionState 
{
    Disconnected,
    Connecting,
    Connected,
    Error
};
```

## 3. 注释规范

### 3.1 文件头注释

```cpp
/**
 * @file DatabaseManager.h
 * @brief 数据库管理类定义
 * @author 作者姓名
 * @date 2024-01-01
 * @version 1.0
 * 
 * 数据库管理类，提供数据库连接、查询、更新等功能。
 * 使用单例模式确保全局只有一个数据库连接实例。
 * 
 * @note 依赖Qt SQL模块
 * @since 1.0
 */
```

### 3.2 类注释

```cpp
/**
 * @class DatabaseManager
 * @brief 数据库管理类
 * 
 * 提供数据库连接、查询、更新等功能。
 * 使用单例模式确保全局只有一个数据库连接实例。
 * 
 * 主要功能：
 * - 数据库连接管理
 * - SQL查询执行
 * - 事务处理
 * - 错误处理
 * 
 * @note 这是一个线程安全的类
 * @warning 使用前必须先调用initialize()方法
 * @see QSqlDatabase
 * @since 1.0
 */
class DatabaseManager
{
    // ...
};
```

### 3.3 函数注释

```cpp
/**
 * @brief 添加伤员记录到数据库
 * 
 * 将伤员信息插入到数据库的injurydatabase表中。
 * 如果数据库连接失败或SQL执行出错，函数将返回false。
 * 
 * @param data 伤员数据结构体，包含以下字段：
 *             - id: 伤员唯一标识符
 *             - rank: 伤情等级 (0:轻微, 1:一般, 2:严重)
 *             - lon: 经度坐标
 *             - lat: 纬度坐标
 *             - flag: 状态标志
 * 
 * @return bool 操作结果
 * @retval true 添加成功
 * @retval false 添加失败（数据库连接失败或SQL执行错误）
 * 
 * @note 调用此函数前需要确保数据库连接正常
 * @warning 不会检查数据的有效性，调用者需要自行验证
 * @see Injury结构体定义
 * @see deleteById()
 * 
 * @example
 * @code
 * Injury injury;
 * injury.id = "001";
 * injury.rank = 1;
 * injury.lon = 113.045292;
 * injury.lat = 28.257748;
 * injury.flag = 1;
 * 
 * bool result = databaseManager->add(injury);
 * if (result) {
 *     qDebug() << "伤员记录添加成功";
 * } else {
 *     qDebug() << "伤员记录添加失败";
 * }
 * @endcode
 */
bool add(const Injury &data);
```

### 3.4 行内注释

```cpp
// 单行注释，解释代码逻辑
int count = 0;  // 计数器，记录处理的记录数

// 复杂逻辑需要详细注释
if (m_database.isOpen() && !userName.isEmpty()) {
    // 数据库已连接且用户名有效，执行查询
    executeQuery(buildSelectQuery(userName));
}

/* 
 * 多行注释用于解释复杂的逻辑
 * 或者描述算法的实现原理
 * 也可以用于临时禁用代码块
 */

/**
 * TODO: 需要优化查询性能
 * FIXME: 修复内存泄漏问题
 * HACK: 临时解决方案，需要后续重构
 * NOTE: 重要说明或提醒
 */
```

## 4. 代码格式规范

### 4.1 缩进和空格

```cpp
// 使用4个空格缩进（不使用Tab）
class MyClass
{
public:
    void myFunction()
    {
        if (condition) {
            doSomething();
        }
        
        // 操作符前后加空格
        int result = a + b * c;
        bool isValid = (x > 0) && (y < 100);
        
        // 函数调用括号前不加空格，参数间加空格
        myFunction(param1, param2);
        
        // 数组访问不加空格
        array[index] = value;
        
        // 指针和引用符号靠近类型
        QString *pointer;
        const QString &reference;
    }
};
```

### 4.2 花括号位置

```cpp
// Qt风格：花括号另起一行
class MyClass
{
public:
    void function()
    {
        if (condition)
        {
            // 代码块
        }
        else
        {
            // 代码块
        }
        
        // 循环语句
        for (int i = 0; i < count; ++i)
        {
            processItem(i);
        }
        
        // switch语句
        switch (value)
        {
        case 1:
            handleCase1();
            break;
        case 2:
            handleCase2();
            break;
        default:
            handleDefault();
            break;
        }
    }
};
```

### 4.3 行长度和换行

```cpp
// 每行不超过100个字符
// 长函数调用需要换行
connect(ui->pushButton, &QPushButton::clicked,
        this, &MyClass::onButtonClicked);

// 长条件语句换行
if (veryLongConditionName && anotherLongConditionName &&
    yetAnotherCondition)
{
    // 处理逻辑
}

// 函数参数过多时换行
void longFunctionName(const QString &firstParameter,
                     int secondParameter,
                     bool thirdParameter,
                     const QObject *fourthParameter);
```

## 5. Qt特定规范

### 5.1 信号和槽

```cpp
class MyWidget : public QWidget
{
    Q_OBJECT

public:
    explicit MyWidget(QWidget *parent = nullptr);

signals:
    /**
     * @brief 数据更新信号
     * @param data 更新的数据
     */
    void dataUpdated(const QString &data);
    
    /**
     * @brief 错误发生信号  
     * @param errorMessage 错误信息
     */
    void errorOccurred(const QString &errorMessage);

public slots:
    /**
     * @brief 设置数据
     * @param data 要设置的数据
     */
    void setData(const QString &data);

private slots:
    /**
     * @brief 按钮点击槽函数
     */
    void on_pushButton_clicked();
    
    /**
     * @brief 处理网络回复
     */
    void handleNetworkReply();

private:
    // 建议使用新的连接语法
    void setupConnections()
    {
        connect(ui->pushButton, &QPushButton::clicked,
                this, &MyWidget::on_pushButton_clicked);
                
        connect(m_networkManager, &QNetworkAccessManager::finished,
                this, &MyWidget::handleNetworkReply);
    }
};
```

### 5.2 属性系统

```cpp
class MyClass : public QObject
{
    Q_OBJECT
    Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
    Q_PROPERTY(int value READ value WRITE setValue NOTIFY valueChanged)

public:
    // 属性读取器
    QString name() const { return m_name; }
    int value() const { return m_value; }
    
    // 属性设置器
    void setName(const QString &name)
    {
        if (m_name != name) {
            m_name = name;
            emit nameChanged();
        }
    }
    
    void setValue(int value)
    {
        if (m_value != value) {
            m_value = value;
            emit valueChanged();
        }
    }

signals:
    void nameChanged();
    void valueChanged();

private:
    QString m_name;
    int m_value = 0;
};
```

### 5.3 Q_OBJECT宏使用

```cpp
// 正确：继承自QObject的类需要Q_OBJECT宏
class MyQObjectClass : public QObject
{
    Q_OBJECT  // 必须在类声明的开始处

public:
    explicit MyQObjectClass(QObject *parent = nullptr);
    
signals:
    void somethingHappened();
};

// 纯数据结构不需要Q_OBJECT
struct DataStructure
{
    QString id;
    int value;
    double coordinate;
};
```

## 6. 错误处理和调试

### 6.1 调试输出

```cpp
#include <QDebug>
#include <QLoggingCategory>

// 定义日志分类
Q_LOGGING_CATEGORY(database, "app.database")
Q_LOGGING_CATEGORY(network, "app.network")

void MyClass::processData()
{
    qCDebug(database) << "开始处理数据...";
    qCDebug(database) << "数据库连接状态:" << m_database.isOpen();
    
    if (!m_database.isOpen()) {
        qCWarning(database) << "数据库未连接";
        return;
    }
    
    // 调试信息输出
    qDebug() << "处理记录数量:" << records.size();
    qInfo() << "用户操作:" << userAction;
    qWarning() << "性能警告: 查询耗时过长";
    qCritical() << "严重错误: 数据库连接丢失";
}
```

### 6.2 异常和错误处理

```cpp
bool DatabaseManager::executeQuery(const QString &sql)
{
    // 参数验证
    if (sql.isEmpty()) {
        qWarning() << "SQL语句为空";
        return false;
    }
    
    if (!m_database.isOpen()) {
        qCritical() << "数据库未连接";
        return false;
    }
    
    try {
        QSqlQuery query(m_database);
        if (!query.prepare(sql)) {
            qCritical() << "SQL预处理失败:" << query.lastError().text();
            return false;
        }
        
        if (!query.exec()) {
            qCritical() << "SQL执行失败:" << query.lastError().text();
            qCritical() << "执行的SQL:" << sql;
            return false;
        }
        
        qDebug() << "SQL执行成功，影响行数:" << query.numRowsAffected();
        return true;
        
    } catch (const std::exception &e) {
        qCritical() << "执行异常:" << e.what();
        return false;
    }
}
```

### 6.3 断言使用

```cpp
#include <QDebug>

void processArray(const QStringList &list, int index)
{
    // 调试版本中检查参数有效性
    Q_ASSERT(!list.isEmpty());
    Q_ASSERT(index >= 0 && index < list.size());
    
    // 生产版本中的参数检查
    if (list.isEmpty()) {
        qWarning() << "列表为空";
        return;
    }
    
    if (index < 0 || index >= list.size()) {
        qWarning() << "索引超出范围:" << index;
        return;
    }
    
    // 处理逻辑
    QString item = list.at(index);
    // ...
}
```

## 7. 内存管理

### 7.1 智能指针使用

```cpp
#include <QScopedPointer>
#include <QSharedPointer>
#include <memory>

class MyClass
{
private:
    // Qt智能指针
    QScopedPointer<QTimer> m_timer;         // 独占所有权
    QSharedPointer<QNetworkReply> m_reply;  // 共享所有权
    
    // 标准库智能指针
    std::unique_ptr<DatabaseConnection> m_connection;
    std::shared_ptr<ConfigManager> m_config;

public:
    MyClass()
        : m_timer(new QTimer(this))  // 自动删除
        , m_connection(std::make_unique<DatabaseConnection>())
    {
        // 初始化
    }
};
```

### 7.2 对象生命周期管理

```cpp
// 使用父子关系管理内存
void createUI()
{
    QWidget *mainWidget = new QWidget;
    
    // 子控件会被父控件自动删除
    QLabel *label = new QLabel("文本", mainWidget);
    QPushButton *button = new QPushButton("按钮", mainWidget);
    
    // 布局也会被父控件管理
    QVBoxLayout *layout = new QVBoxLayout(mainWidget);
    layout->addWidget(label);
    layout->addWidget(button);
}

// 手动管理生命周期
void processData()
{
    // 使用栈对象，自动销毁
    QSqlQuery query;
    
    // 或使用智能指针
    QScopedPointer<QNetworkAccessManager> manager(new QNetworkAccessManager);
    
    // 处理逻辑...
} // 函数结束时自动销毁
```

## 8. 性能优化建议

### 8.1 字符串处理

```cpp
// 优先使用const引用传递字符串
void processString(const QString &str)  // 好
{
    // 处理逻辑
}

void processString(QString str)  // 避免，会产生拷贝
{
    // 处理逻辑
}

// 字符串拼接优化
QString buildQuery(const QStringList &fields, const QString &table)
{
    // 使用QStringBuilder或预分配容量
    QString query;
    query.reserve(100);  // 预分配空间
    
    query += "SELECT ";
    query += fields.join(", ");
    query += " FROM ";
    query += table;
    
    return query;
}
```

### 8.2 容器使用

```cpp
// 优先使用const引用遍历
void processItems(const QStringList &items)
{
    // 使用基于范围的for循环
    for (const QString &item : items) {
        processItem(item);
    }
    
    // 或使用const迭代器
    for (auto it = items.cbegin(); it != items.cend(); ++it) {
        processItem(*it);
    }
}

// 预分配容器大小
QStringList buildList(int expectedSize)
{
    QStringList list;
    list.reserve(expectedSize);  // 避免频繁重新分配
    
    for (int i = 0; i < expectedSize; ++i) {
        list.append(QString::number(i));
    }
    
    return list;
}
```

## 9. 代码审查检查清单

### 9.1 基本检查
- [ ] 头文件包含保护符正确
- [ ] 包含文件顺序正确（系统 -> 第三方 -> 项目内部）
- [ ] 命名规范符合要求
- [ ] 缩进和格式一致
- [ ] 没有多余的空白行

### 9.2 功能检查
- [ ] 函数功能单一，职责明确
- [ ] 参数验证充分
- [ ] 错误处理完善
- [ ] 内存管理正确
- [ ] 线程安全（如需要）

### 9.3 Qt特定检查
- [ ] Q_OBJECT宏位置正确
- [ ] 信号槽连接使用新语法
- [ ] 父子关系设置正确
- [ ] 元对象系统使用得当

### 9.4 文档检查
- [ ] 公有接口有完整注释
- [ ] 复杂逻辑有行内注释
- [ ] 文件头信息完整
- [ ] 示例代码正确

## 10. 工具推荐

### 10.1 代码格式化工具
- **clang-format**: 自动格式化代码
- **Qt Creator**: 内置代码格式化功能

### 10.2 静态分析工具
- **clang-static-analyzer**: 静态代码分析
- **cppcheck**: C++静态分析工具
- **PVS-Studio**: 商业静态分析工具

### 10.3 文档生成工具
- **Doxygen**: 从注释生成文档
- **qdoc**: Qt官方文档工具

---

**注意事项：**
1. 本规范基于Qt官方编码风格和现代C++最佳实践
2. 团队应该保持一致的编码风格
3. 新项目应该严格遵循这些规范
4. 现有项目可以逐步重构以符合规范
5. 定期进行代码审查以确保规范执行
