前端学C++可太简单了:预处理器

1. 概念对比:JavaScript编译时 vs C++预处理

JS/TS 编译时处理

javascript 复制代码
// 1. 模块打包时的条件编译
if (process.env.NODE_ENV === 'development') {
    console.log('开发模式');
}

// 2. TypeScript 条件类型
type ApiResponse<T> = T extends string ? string[] : T[];

// 3. Webpack DefinePlugin
const API_URL = __API_URL__; // 编译时替换

// 4. 模块导入路径解析
import utils from '@/utils'; // @ 符号会被编译器处理

C++ 预处理器

cpp 复制代码
// 1. 条件编译
#ifdef DEBUG
    std::cout << "调试模式" << std::endl;
#endif

// 2. 宏定义
#define MAX(a, b) ((a) > (b) ? (a) : (b))

// 3. 常量定义
#define API_URL "https://api.example.com"

// 4. 文件包含
#include <iostream>  // 预处理器会插入整个文件内容

2. 预处理器指令

2.1 文件包含 #include (类似 import)

cpp 复制代码
// 系统头文件 - 使用尖括号
#include <iostream>    // 从系统标准库搜索
#include <vector>      // 编译器预定义路径
#include <string>

// 用户头文件 - 使用双引号  
#include "MyClass.hpp"       // 从当前目录搜索
#include "utils/helper.hpp"  // 相对路径
#include "../common/base.hpp" // 父目录

// ThreePP 项目示例
#include "threepp/threepp.hpp"
#include "threepp/cameras/PerspectiveCamera.hpp"

与JavaScript对比:

javascript 复制代码
// JavaScript - 运行时动态加载
import { useState } from 'react';           // ← 模块系统
import MyComponent from './MyComponent';    // ← 相对路径
import utils from '@/utils';                // ← 路径别名

// C++ - 编译时文本替换
#include <iostream>        // ← 预处理器直接插入文件内容
#include "MyClass.hpp"     // ← 文本级别的复制粘贴

2.2 宏定义 #define (类似常量和函数)

简单常量宏

cpp 复制代码
// 数值常量
#define PI 3.14159
#define MAX_SIZE 1000
#define VERSION "1.0.0"

// 使用
double area = PI * radius * radius;
int buffer[MAX_SIZE];
std::cout << "版本: " << VERSION << std::endl;

JavaScript对比:

javascript 复制代码
// JavaScript
const PI = 3.14159;
const MAX_SIZE = 1000;
const VERSION = "1.0.0";

// 或者使用 enum
enum Config {
    MAX_SIZE = 1000
}

函数式宏 (类似JavaScript函数)

cpp 复制代码
// 简单函数宏
#define MAX(a, b) ((a) > (b) ? (a) : (b))
#define MIN(a, b) ((a) < (b) ? (a) : (b))
#define SQUARE(x) ((x) * (x))

// 多行宏 - 使用反斜杠续行
#define DEBUG_PRINT(var) \
    std::cout << #var << " = " << var << std::endl

// 使用示例
int result = MAX(10, 20);        // 展开为: ((10) > (20) ? (10) : (20))
int sq = SQUARE(5);              // 展开为: ((5) * (5))
DEBUG_PRINT(result);             // 输出: result = 20

JavaScript对比:

javascript 复制代码
// JavaScript - 真正的函数
const MAX = (a, b) => a > b ? a : b;
const MIN = (a, b) => a < b ? a : b;
const SQUARE = x => x * x;

// 模板字符串类似功能
const debugPrint = (name, value) => console.log(`${name} = ${value}`);

2.3 条件编译 (类似 if...else)

基础条件编译

cpp 复制代码
// 调试版本 vs 发布版本
#ifdef DEBUG
    #define LOG(msg) std::cout << "[DEBUG] " << msg << std::endl
#else
    #define LOG(msg)  // 空宏,发布版本不输出
#endif

// 平台特定代码
#ifdef _WIN32
    #include <windows.h>
    #define SLEEP(ms) Sleep(ms)
#elif defined(__linux__)
    #include <unistd.h>
    #define SLEEP(ms) usleep(ms * 1000)
#elif defined(__APPLE__)
    #include <unistd.h>
    #define SLEEP(ms) usleep(ms * 1000)
#endif

JavaScript对比:

javascript 复制代码
// JavaScript - 运行时条件
if (process.env.NODE_ENV === 'development') {
    console.log('[DEBUG]', msg);
}

// Webpack DefinePlugin 编译时替换
if (__DEV__) {  // 编译时会被替换为 true 或 false
    console.log('[DEBUG]', msg);
}

复杂条件编译

cpp 复制代码
// 检查编译器特性
#if __cplusplus >= 201703L  // C++17或更高
    #include <optional>
    using optional_int = std::optional<int>;
#else
    // 自定义optional实现
    #include "my_optional.hpp"
    using optional_int = my_optional<int>;
#endif

// 检查宏是否定义
#ifndef BUFFER_SIZE
    #define BUFFER_SIZE 1024  // 如果没有定义,则使用默认值
#endif

// 多条件判断
#if defined(USE_OPENGL) && !defined(USE_VULKAN)
    #include "opengl_renderer.hpp"
    using Renderer = OpenGLRenderer;
#elif defined(USE_VULKAN)
    #include "vulkan_renderer.hpp"
    using Renderer = VulkanRenderer;
#else
    #error "Must define either USE_OPENGL or USE_VULKAN"
#endif

2.4 预定义宏 (类似全局变量)

cpp 复制代码
#include <iostream>

int main() {
    // 文件信息
    std::cout << "文件: " << __FILE__ << std::endl;
    std::cout << "行号: " << __LINE__ << std::endl;
    std::cout << "函数: " << __FUNCTION__ << std::endl;

    // 编译信息  
    std::cout << "编译日期: " << __DATE__ << std::endl;
    std::cout << "编译时间: " << __TIME__ << std::endl;

    // C++标准版本
    std::cout << "C++版本: " << __cplusplus << std::endl;

    // 编译器信息
    #ifdef _MSC_VER
        std::cout << "编译器: MSVC " << _MSC_VER << std::endl;
    #elif defined(__GNUC__)
        std::cout << "编译器: GCC " << __GNUC__ << "." << __GNUC_MINOR__ << std::endl;
    #elif defined(__clang__)
        std::cout << "编译器: Clang " << __clang_major__ << "." << __clang_minor__ << std::endl;
    #endif

    return 0;
}

JavaScript对比:

javascript 复制代码
// JavaScript - 运行时信息
console.log('文件:', import.meta.url);  // ES modules
console.log('Node版本:', process.version);
console.log('平台:', process.platform);

// 编译时信息(需要构建工具支持)
console.log('构建时间:', __BUILD_TIME__);
console.log('版本:', process.env.npm_package_version);
相关推荐
猩猩程序员10 分钟前
Go 1.24 全面拥抱 Swiss Table:让内置 map 提速 60% 的秘密
前端
1024小神11 分钟前
vue3 + vite项目,如果在build的时候对代码加密混淆
前端·javascript
郝学胜-神的一滴12 分钟前
C++中的`auto`与`std::any`:功能、区别与选择建议
开发语言·c++·程序人生·算法
轻语呢喃30 分钟前
useRef :掌握 DOM 访问与持久化状态的利器
前端·javascript·react.js
wwy_frontend1 小时前
useState 的 9个常见坑与最佳实践
前端·react.js
w_y_fan1 小时前
flutter_riverpod: ^2.6.1 应用笔记 (一)
前端·flutter
Jerry1 小时前
Compose 界面工具包
前端
Focusbe1 小时前
从0到1开发一个AI助手
前端·人工智能·面试
egghead263161 小时前
React组件通信
前端·react.js
RIKA1 小时前
【前端工具】使用 Node.js 脚本实现项目打包后自动压缩
前端