C++代码格式化艺术:提升可读性与维护性的全面指南

代码的格式化风格不仅关系到项目的美观,更是团队协作的重要基础。良好的代码排版能够提高可读性、降低错误率、加快代码审查速度,最终提升整个开发团队的效率。本文将深入探讨C/C++代码格式化的各个方面,从空白行的使用到类的布局,结合理论和实例,帮助开发者建立专业、一致且易于维护的代码风格。

3.1 空行的战略应用

空行是代码可读性的无形助手,合理使用空行可以将逻辑相关的代码分组,使代码结构更加清晰。

空行的基本原则

  1. 逻辑分组:使用空行分隔不同的逻辑部分
  2. 适度使用:过多的空行会使代码过于分散,过少则会使代码过于拥挤
  3. 一致性:在整个代码库中保持一致的空行使用模式

实践建议与示例

示例1:函数定义之间的空行

cpp

#include <iostream>
#include <string>

// 计算两个整数的和
int add(int a, int b) {
    return a + b;
}

// 计算两个整数的差
int subtract(int a, int b) {
    return a - b;
}

// 计算两个整数的乘积
int multiply(int a, int b) {
    return a * b;
}

示例2:类定义中的空行

cpp

class BankAccount {
private:
    std::string accountNumber;
    std::string ownerName;
    double balance;
    
public:
    // 构造函数和析构函数
    BankAccount(const std::string& number, const std::string& name);
    ~BankAccount();
    
    // 账户操作方法
    bool deposit(double amount);
    bool withdraw(double amount);
    double getBalance() const;
    
    // 账户信息方法
    std::string getAccountInfo() const;
    void printStatement() const;
};

示例3:逻辑块之间的空行

cpp

void processUserData() {
    // 读取用户输入
    std::string userName = getUserName();
    int userAge = getUserAge();
    std::string userEmail = getUserEmail();
    
    // 验证用户数据
    if (!isValidName(userName)) {
        reportError("Invalid name");
        return;
    }
    
    if (!isValidAge(userAge)) {
        reportError("Invalid age");
        return;
    }
    
    // 保存用户数据到数据库
    UserRecord record(userName, userAge, userEmail);
    database.saveRecord(record);
    
    // 发送确认邮件
    EmailService::sendConfirmation(userEmail);
}

何时不应使用空行

不是所有地方都适合添加空行,例如:

  1. 相邻的变量声明之间,尤其是相关的变量
  2. 非常短的函数体内
  3. return语句前,除非前面有较复杂的逻辑块

3.2 代码行的组织与长度

控制代码行的长度和组织方式对于可读性至关重要,特别是在团队协作和代码审查过程中。

理想的行长度

虽然现代显示器能够显示很长的行,但为了可读性,建议遵循以下原则:

  1. 限制行长:通常在80-100个字符之间
  2. 考虑可见性:避免水平滚动,尤其是在代码审查工具中
  3. 平衡简洁和清晰:不要为了缩短行而牺牲代码的清晰度

换行技巧与实践

当代码行超过理想长度时,应当进行换行处理。以下是一些常用的换行技巧:

示例1:长函数调用的换行

cpp

// 不好的方式
void processComplexData(const std::string& inputData, int processingLevel, bool validateResults, const std::vector<double>& initialParameters, ProcessingCallback callback) {
    // 函数体
}

// 推荐的方式
void processComplexData(
    const std::string& inputData,
    int processingLevel,
    bool validateResults,
    const std::vector<double>& initialParameters,
    ProcessingCallback callback
) {
    // 函数体
}

示例2:长表达式的换行

cpp

// 不好的方式
double result = firstTerm + secondTerm * (thirdTerm + fourthTerm) / fifthTerm - sixthTerm + seventhTerm * eighthTerm;

// 推荐的方式 - 按照运算符优先级换行
double result = firstTerm 
                + secondTerm * (thirdTerm + fourthTerm) / fifthTerm 
                - sixthTerm 
                + seventhTerm * eighthTerm;

示例3:条件语句的换行

cpp

// 不好的方式
if (condition1 && condition2 && (condition3 || condition4) && !condition5) {
    // 执行操作
}

// 推荐的方式
if (condition1 
    && condition2 
    && (condition3 || condition4) 
    && !condition5) {
    // 执行操作
}

// 或者使用临时变量提高可读性
bool isValid = condition1 && condition2;
bool hasOptionalFeatures = condition3 || condition4;
bool isNotRestricted = !condition5;

if (isValid && hasOptionalFeatures && isNotRestricted) {
    // 执行操作
}

3.3 代码行内的空格运用

适当使用空格可以增强代码的可读性,使代码结构更加清晰,关键元素更加突出。

空格使用的基本原则

  1. 运算符周围:在二元运算符两侧添加空格,使运算表达式更易读
  2. 逗号后面:在逗号后面添加空格,提高可读性
  3. 括号内外:遵循一致的空格使用规则

详细示例

示例1:运算符周围的空格

cpp

// 不好的格式
int sum=a+b*c;
if(x==y&&z>0){
    doSomething();
}

// 推荐的格式
int sum = a + b * c;
if (x == y && z > 0) {
    doSomething();
}

示例2:函数调用和定义中的空格

cpp

// 不好的格式
void calculateArea(double length,double width){
    double area=length*width;
    return area;
}

calculateArea(5.0,3.0);

// 推荐的格式
void calculateArea(double length, double width) {
    double area = length * width;
    return area;
}

calculateArea(5.0, 3.0);

示例3:括号和大括号中的空格

cpp

// 不好的格式 - 不一致的空格使用
if( condition ){
    statement1;
}else{
    statement2;
}

// 推荐的格式 - 一致的空格使用
if (condition) {
    statement1;
} else {
    statement2;
}

示例4:循环和条件语句中的空格

cpp

// 不好的格式
for(int i=0;i<10;i++){
    if(array[i]>max)max=array[i];
}

// 推荐的格式
for (int i = 0; i < 10; i++) {
    if (array[i] > max) {
        max = array[i];
    }
}

特殊情况

某些特殊情况下,可以有选择地忽略空格以提高可读性:

cpp

// 特殊情况示例:矩阵初始化
Matrix3x3 rotation = {
    {1.0f, 0.0f, 0.0f},
    {0.0f, cosf(angle), -sinf(angle)},
    {0.0f, sinf(angle), cosf(angle)}
};

// 左值引用和右值引用
void process(const std::string& name);  // 左值引用,添加空格
void process(std::string&& name);       // 右值引用,不添加空格

3.4 代码对齐技巧

代码对齐是一种强大的视觉辅助工具,可以突出变量、注释或相关代码元素之间的关系。

对齐的基本原则

  1. 适度使用:对齐应该提高可读性,而不是为了美观而牺牲维护性
  2. 局部对齐:在逻辑相关的小块代码中使用对齐,而不是跨越大段代码
  3. 保持一致:在项目中保持一致的对齐风格

有效的对齐实践

示例1:变量声明对齐

cpp

// 有意义的对齐方式
class Customer {
private:
    int         id;          // 唯一标识符
    std::string firstName;   // 客户名
    std::string lastName;    // 客户姓
    double      balance;     // 账户余额
    bool        isActive;    // 账户状态
};

示例2:赋值语句对齐

cpp

// 相关变量赋值的对齐
Rectangle rect;
rect.x      = 100;
rect.y      = 200;
rect.width  = 300;
rect.height = 400;

示例3:注释对齐

cpp

void renderScene() {
    setupLights();      // 配置场景光源
    drawBackground();   // 绘制背景层
    drawTerrain();      // 绘制地形
    drawObjects();      // 绘制场景对象
    drawEffects();      // 绘制特效
    drawUI();           // 绘制用户界面
}

对齐的潜在问题

对齐虽然有助于可读性,但也存在一些潜在问题:

  1. 维护成本:对齐的代码更改一行可能需要重新调整多行
  2. 版本控制差异:可能导致大量无关代码出现在差异中
  3. 编辑器差异:不同编辑器处理制表符和空格的方式可能不同

推荐做法

  • 在小的相关代码块中使用对齐
  • 使用自动格式化工具保持一致性
  • 避免过度依赖对齐作为代码组织的主要方式

3.5 长行的拆分策略

当代码行过长时,需要采用适当的拆分策略来保持可读性和可维护性。

长行拆分的基本原则

  1. 在逻辑断点处拆分:如运算符、逗号、参数分隔处
  2. 保持清晰的缩进:后续行应有明确的缩进以表示连续性
  3. 保持相关元素对齐:提高可读性

不同情况下的拆分技巧

示例1:长表达式的拆分

cpp

// 不好的拆分
double result = a * b + c * d - 
e / f + g * (h + i);

// 推荐的拆分 - 在运算符前拆分,后续行对齐
double result = a * b + c * d 
              - e / f 
              + g * (h + i);

示例2:长函数声明的拆分

cpp

// 不好的拆分
std::vector<std::pair<std::string, double>> processTransactions(const std::vector<Transaction>& transactions, TransactionType type, bool includeDetails, double minimumAmount);

// 推荐的拆分 - 参数列表换行并缩进
std::vector<std::pair<std::string, double>> processTransactions(
    const std::vector<Transaction>& transactions,
    TransactionType type,
    bool includeDetails,
    double minimumAmount
);

示例3:长条件语句的拆分

cpp

// 不好的拆分
if (user.isAuthenticated() && user.hasPermission("edit") && !document.isLocked() && document.getOwner() == user.getId()) {
    // 允许编辑
}

// 推荐的拆分 - 使用逻辑运算符作为拆分点
if (user.isAuthenticated() 
    && user.hasPermission("edit") 
    && !document.isLocked() 
    && document.getOwner() == user.getId()) {
    // 允许编辑
}

// 或者使用临时变量提高可读性
bool isAuthenticatedUser = user.isAuthenticated() && user.hasPermission("edit");
bool isEditableDocument = !document.isLocked() && document.getOwner() == user.getId();

if (isAuthenticatedUser && isEditableDocument) {
    // 允许编辑
}

示例4:长字符串的拆分

cpp

// 不好的拆分
std::string message = "This is a very long message that needs to be displayed to the user. It contains important information about the system status.";

// C++11及以上版本推荐的拆分 - 使用字符串字面量的自动连接
std::string message = "This is a very long message that needs to be "
                      "displayed to the user. It contains important "
                      "information about the system status.";

// 另一种方法 - 使用+运算符(可能有性能影响)
std::string message = "This is a very long message that needs to be " +
                      "displayed to the user. It contains important " +
                      "information about the system status.";

3.6 修饰符的最佳位置

修饰符(如const、volatile、&、*等)的放置位置会影响代码的可读性和含义解释。

理论基础与最佳实践

在C++中,有两种主要的修饰符放置风格:

  1. 靠左风格(C风格):修饰符放在类型左侧
  2. 靠右风格(C++风格):修饰符靠近变量名

不同修饰符的放置建议

示例1:指针和引用修饰符

cpp

// 靠左风格(C风格)
char *name;
const char *title;
char *names[10];

// 靠右风格(C++风格)- 更清晰地表明变量的确切类型
char* name;
const char* title;
char* names[10];

// 多个声明时,靠右风格的优势更明显
char *first, *second;  // 在C风格中,只有first是指针,second是char
char* first, second;   // 在C++风格中,类型更明确:first是指针,second是char

示例2:const修饰符的位置

cpp

// 返回常量引用
const std::string& getName() const;

// 常量指针参数
void processData(const char* data);

// 指向常量的指针 vs 常量指针
const char* immutableData;  // 指向常量字符的指针(数据不可修改)
char* const fixedPointer = buffer;  // 常量指针(指针不可修改)

示例3:多重修饰符

cpp

// 指向常量的常量指针
const char* const COMPANY_NAME = "Acme Inc.";

// 常量引用
void display(const std::string& text);

// 右值引用
void process(std::vector<int>&& values);

一致性原则

无论选择哪种风格,最重要的是在整个项目中保持一致。以下是一些推荐的一致性原则:

  1. 对于团队项目,遵循既定的编码规范
  2. 对于新项目,C++中通常推荐靠右风格(修饰符靠近变量名)
  3. 在库API设计中,清晰地表达修饰符的语义

3.7 注释的艺术

注释是代码可读性和可维护性的关键组成部分,但过多或不恰当的注释反而可能降低代码质量。

注释的原则

  1. 注释为什么,而不是什么:代码本身应该表达它做了什么,注释应该解释为什么
  2. 避免过度注释:好的代码应该是自文档化的,不需要过多注释
  3. 保持注释的更新:过时的注释比没有注释更有害

有效注释的类型与示例

示例1:文件头注释

cpp

/**
 * @file   UserManager.h
 * @brief  用户管理系统的核心组件
 * 
 * 该组件负责用户账户的创建、认证、权限管理和生命周期维护。
 * 设计为线程安全,支持高并发操作。
 * 
 * @author 张三 <zhangsan@example.com>
 * @date   2025-10-30
 */

示例2:函数注释

cpp

/**
 * 尝试将用户名和密码匹配进行用户验证
 * 
 * @param username 用户提供的用户名
 * @param password 用户提供的密码(明文)
 * @param lockoutPolicy 可选的账户锁定策略
 * 
 * @return 包含验证结果和会话令牌的结构体(验证失败时令牌为空)
 * 
 * @throws DatabaseException 当数据库连接失败时
 * @throws RateLimitException 当超过验证尝试限制时
 * 
 * @note 此函数会记录所有失败的验证尝试
 */
AuthResult authenticateUser(
    const std::string& username,
    const std::string& password,
    const LockoutPolicy& lockoutPolicy = DefaultLockoutPolicy
);

示例3:实现细节注释

cpp

void User::resetPassword(const std::string& newPassword) {
    // 确保密码符合复杂性要求
    if (!PasswordPolicy::meetsComplexityRequirements(newPassword)) {
        throw InvalidPasswordException("Password does not meet complexity requirements");
    }
    
    // 生成新的盐值以增强安全性
    std::string salt = SecurityUtils::generateRandomSalt();
    
    // 使用PBKDF2算法和盐值哈希密码
    // 迭代次数设为10000以抵抗暴力破解
    std::string hashedPassword = SecurityUtils::hashWithPBKDF2(newPassword, salt, 10000);
    
    // 更新存储的密码和盐值
    this->passwordHash = hashedPassword;
    this->passwordSalt = salt;
    this->passwordLastChanged = std::chrono::system_clock::now();
    
    // 强制用户在下次登录时更改临时密码
    if (this->status == UserStatus::TEMP_PASSWORD) {
        this->mustChangePassword = true;
    }
}

示例4:TODO和FIXME注释

cpp

// TODO(zhangsan): 实现缓存以提高频繁查询的性能
// 预计在v2.3版本中添加

// FIXME: 在高并发情况下可能存在竞态条件
// 需要添加互斥锁或使用原子操作

避免的注释类型

以下类型的注释通常应该避免:

  1. 重述代码的注释

cpp

// 不好的注释 - 仅重述代码
// 将计数器加1
counter++;

// 不好的注释 - 明显的信息
// 检查用户是否为null
if (user == nullptr) {
    return false;
}
  1. 过时或不准确的注释

cpp

// 不好的注释 - 与代码不符
// 使用MD5哈希算法
// (但代码实际使用了SHA-256)
std::string hash = HashUtils::computeSHA256(data);
  1. 分隔符或装饰性注释

cpp

// 不好的注释风格 - 过于花哨
//********************************************
//**     用户验证函数                        **
//********************************************

// 更好的替代方式 - 简洁且信息丰富
// 用户验证相关函数

3.8 类的布局与格式规范

类的组织结构对其可读性和可维护性有重大影响。良好的类布局可以帮助开发人员快速理解类的功能和接口。

类布局的基本原则

  1. 分组相关成员:将相关的方法和属性分组在一起
  2. 访问控制顺序:通常按public、protected、private的顺序排列
  3. 逻辑顺序:在每个访问控制部分内,遵循逻辑顺序(如构造/析构、操作方法、辅助方法等)

推荐的类布局示例

cpp

/**
 * @class DatabaseConnection
 * @brief 管理与数据库的连接和交互
 */
class DatabaseConnection {
public:
    // 1. 类型定义和枚举
    enum class State { DISCONNECTED, CONNECTING, CONNECTED, ERROR };
    using ConnectionCallback = std::function<void(State)>;
    
    // 2. 构造函数和析构函数
    DatabaseConnection();
    explicit DatabaseConnection(const ConnectionString& connStr);
    DatabaseConnection(const DatabaseConnection&) = delete;  // 禁用复制
    DatabaseConnection& operator=(const DatabaseConnection&) = delete;
    ~DatabaseConnection();
    
    // 3. 主要功能方法
    bool connect(const ConnectionString& connStr);
    void disconnect();
    State getState() const;
    
    // 4. 数据操作方法
    QueryResult executeQuery(const std::string& query);
    bool executeUpdate(const std::string& update);
    PreparedStatement prepareStatement(const std::string& query);
    
    // 5. 事件处理和回调
    void setConnectionStateCallback(ConnectionCallback callback);
    
    // 6. 辅助方法
    std::string getLastError() const;
    bool isConnected() const { return state_ == State::CONNECTED; }

protected:
    // 1. 保护方法(供子类使用)
    void onConnectionStateChange(State newState);
    
    // 2. 可重写的虚方法
    virtual void handleConnectionError(const std::string& errorMessage);

private:
    // 1. 私有辅助方法
    bool validateConnectionString(const ConnectionString& connStr);
    void initializeConnection();
    void cleanupConnection();
    
    // 2. 数据成员
    ConnectionString connectionString_;
    State state_;
    ConnectionCallback stateCallback_;
    std::unique_ptr<DatabaseHandle> handle_;
    std::string lastError_;
    
    // 3. 静态成员
    static std::atomic<int> activeConnections_;
};

多继承与复杂类的布局

对于涉及多重继承或实现多个接口的复杂类,应当特别注意布局清晰度:

cpp

/**
 * @class AdvancedUIComponent
 * @brief 实现高级UI组件,支持拖放、缩放和样式自定义
 */
class AdvancedUIComponent : 
    public UIComponent,                  // 基本UI功能
    public DragDropTarget,               // 拖放功能
    public Resizable,                    // 缩放功能
    private StyleChangeObserver,         // 样式变化通知(内部实现)
    public std::enable_shared_from_this<AdvancedUIComponent>  // 智能指针支持
{
public:
    // 1. 从UIComponent继承的接口实现
    void render() override;
    void update() override;
    
    // 2. 从DragDropTarget继承的接口实现
    bool acceptDrop(const DragItem& item) override;
    void onDragEnter(const DragItem& item) override;
    void onDragLeave() override;
    void onDrop(const DragItem& item) override;
    
    // 3. 从Resizable继承的接口实现
    void resize(int width, int height) override;
    ResizeHandles getResizeHandles() const override;
    
    // 4. 本类特有的公共方法
    void setCustomStyle(const Style& style);
    const Style& getStyle() const;

private:
    // 1. 从StyleChangeObserver继承的私有实现
    void onStyleChanged(const StyleChangeEvent& event) override;
    
    // 2. 私有辅助方法
    void updateLayout();
    void recalculateSize();
    
    // 3. 数据成员
    Style currentStyle_;
    bool isDragging_;
    bool isResizing_;
    ResizeHandleType activeResizeHandle_;
};

模板类的布局特殊考虑

模板类通常需要在头文件中包含完整实现,这会影响布局策略:

cpp

/**
 * @class CircularBuffer
 * @brief 实现固定大小的循环缓冲区
 * 
 * @tparam T 缓冲区元素类型
 * @tparam Allocator 内存分配器类型
 */
template <typename T, typename Allocator = std::allocator<T>>
class CircularBuffer {
public:
    // 类型定义
    using value_type = T;
    using allocator_type = Allocator;
    using size_type = std::size_t;
    using reference = T&;
    using const_reference = const T&;
    
    // 构造和析构
    explicit CircularBuffer(size_type capacity);
    CircularBuffer(const CircularBuffer& other);
    CircularBuffer(CircularBuffer&& other) noexcept;
    CircularBuffer& operator=(const CircularBuffer& other);
    CircularBuffer& operator=(CircularBuffer&& other) noexcept;
    ~CircularBuffer();
    
    // 公共方法...
    
private:
    // 私有成员...
};

// 模板实现(通常在同一个头文件中)
template <typename T, typename Allocator>
CircularBuffer<T, Allocator>::CircularBuffer(size_type capacity)
    : capacity_(capacity),
      size_(0),
      head_(0),
      tail_(0) {
    // 初始化实现...
}

// 其他方法实现...

实践总结与工具应用

代码格式化不必总是手动进行,现代开发环境提供了各种工具来自动化这个过程。

自动格式化工具

  1. Clang-Format:最流行的C++代码格式化工具,可高度自定义

    • 示例配置文件(.clang-format):

    yaml

    BasedOnStyle: Google
    IndentWidth: 4
    ColumnLimit: 100
    AllowShortFunctionsOnASingleLine: Empty
    AllowShortIfStatementsOnASingleLine: false
    BreakBeforeBraces: Stroustrup
    
  2. Visual Studio的格式化功能

    • 使用方法:Edit > Advanced > Format Document (Ctrl+K, Ctrl+D)
  3. VS Code扩展

    • C/C++ Extension: 提供基于clang-format的格式化
    • 配置示例(settings.json):

    json

    {
        "C_Cpp.clang_format_style": "file",
        "editor.formatOnSave": true,
        "C_Cpp.formatting": "clangFormat"
    }
    

团队一致性的实现

对于团队项目,应当:

  1. 制定明确的编码规范:包括本文讨论的所有格式化方面
  2. 使用版本控制的配置文件:将格式化工具配置文件纳入版本控制
  3. 在CI/CD流程中集成格式检查:确保所有代码提交遵循团队规范

实际项目示例

以下是一个结合了本文讨论的各种格式化原则的简短但完整的C++类示例:

cpp

/**
 * @file   ShapeRenderer.h
 * @brief  用于渲染各种几何图形的工具类
 * 
 * 该类使用OpenGL或DirectX后端实现高效的图形渲染。
 * 支持2D和简单的3D图形,适用于简单的可视化和UI绘制。
 * 
 * @author 李四 <lisi@example.com>
 * @date   2025-10-28
 */

#ifndef GRAPHICS_SHAPE_RENDERER_H
#define GRAPHICS_SHAPE_RENDERER_H
#pragma once

#include <vector>
#include <string>
#include <memory>
#include "Graphics/Color.h"
#include "Graphics/RenderContext.h"

// 前向声明
namespace Graphics {
    class Texture;
    class Shader;
}

namespace Graphics {

/**
 * 渲染器的配置选项
 */
struct RendererOptions {
    bool enableAntialiasing = true;  // 是否启用抗锯齿
    float lineThickness = 1.0f;      // 线条粗细
    Color defaultColor{255, 255, 255, 255};  // 默认颜色(白色)
    
    RendererOptions() = default;
    explicit RendererOptions(bool antialiasing) : enableAntialiasing(antialiasing) {}
};

/**
 * @class ShapeRenderer
 * @brief 提供各种几何图形的高效渲染功能
 */
class ShapeRenderer {
public:
    // 形状类型枚举
    enum class ShapeType {
        Line,
        Rectangle,
        Circle,
        Triangle,
        Polygon
    };
    
    // 构造和析构
    explicit ShapeRenderer(RenderContext* context);
    ShapeRenderer(RenderContext* context, const RendererOptions& options);
    ~ShapeRenderer();
    
    // 禁用复制
    ShapeRenderer(const ShapeRenderer&) = delete;
    ShapeRenderer& operator=(const ShapeRenderer&) = delete;
    
    // 渲染方法
    void drawLine(
        float x1, 
        float y1, 
        float x2, 
        float y2, 
        const Color& color = Color()
    );
    
    void drawRectangle(
        float x, 
        float y, 
        float width, 
        float height, 
        const Color& color = Color(),
        bool filled = true
    );
    
    void drawCircle(
        float centerX, 
        float centerY, 
        float radius, 
        const Color& color = Color(),
        bool filled = true,
        int segments = 36
    );
    
    // 绘制多边形,points应为偶数个,表示顶点的x和y坐标
    void drawPolygon(
        const std::vector<float>& points, 
        const Color& color = Color(),
        bool filled = true
    );
    
    // 绘制带纹理的矩形
    void drawTexturedRectangle(
        float x, 
        float y, 
        float width, 
        float height, 
        const Texture* texture,
        const Color& tint = Color(255, 255, 255, 255)
    );
    
    // 配置方法
    void setOptions(const RendererOptions& options);
    const RendererOptions& getOptions() const { return options_; }
    
    void begin();  // 开始一批渲染操作
    void end();    // 结束并提交批处理
    
    // 状态查询
    bool isActive() const { return isActive_; }
    int getDrawCallCount() const { return drawCallCount_; }
    
private:
    // 私有辅助方法
    void initialize();
    void setupShaders();
    void flushBatch();
    
    // 不同形状的特定绘制实现
    void drawLineImpl(float x1, float y1, float x2, float y2, const Color& color);
    void drawFilledRectImpl(float x, float y, float width, float height, const Color& color);
    void drawCircleImpl(
        float centerX, 
        float centerY, 
        float radius, 
        const Color& color,
        bool filled,
        int segments
    );
    
    // 错误处理
    void reportError(const std::string& message);
    
    // 成员变量
    RenderContext* context_;                 // 渲染上下文
    RendererOptions options_;                // 渲染选项
    bool isActive_;                          // 是否在批处理中
    int drawCallCount_;                      // 绘制调用次数
    
    std::unique_ptr<Shader> shader_;         // 着色器程序
    std::vector<float> vertexBuffer_;        // 顶点缓冲
    std::vector<unsigned int> indexBuffer_;  // 索引缓冲
    
    static constexpr int MAX_VERTICES = 2048;  // 最大顶点数
    static constexpr int VERTEX_SIZE = 9;      // 每个顶点的浮点数(位置+颜色+纹理坐标)
};

} // namespace Graphics

#endif // GRAPHICS_SHAPE_RENDERER_H

通过遵循本文介绍的代码格式化最佳实践,开发者可以显著提高代码的可读性和可维护性。一致且专业的代码风格不仅有助于减少错误,也能提高团队协作效率和代码审查的有效性。记住,好的代码不仅要正确运行,还应该易于阅读和理解。

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐