前端学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);
相关推荐
励志不掉头发的内向程序员2 小时前
C++进阶——继承 (1)
开发语言·c++·学习
Zacks_xdc3 小时前
【前端】使用Vercel部署前端项目,api转发到后端服务器
运维·服务器·前端·安全·react.js
给月亮点灯|3 小时前
Vue基础知识-脚手架开发-使用Axios发送异步请求+代理服务器解决前后端分离项目的跨域问题
前端·javascript·vue.js
叫我阿柒啊3 小时前
从Java全栈到前端框架:一次真实的面试对话与技术解析
java·javascript·typescript·vue·springboot·react·前端开发
张迅之3 小时前
【React】Ant Design 5.x 实现tabs圆角及反圆角效果
前端·react.js·ant-design
@CLoudbays_Martin113 小时前
为什么动态视频业务内容不可以被CDN静态缓存?
java·运维·服务器·javascript·网络·python·php
蔗理苦4 小时前
2025-09-05 CSS3——盒子模型
前端·css·css3
mit6.8244 小时前
并查集|栈
c++
中国胖子风清扬5 小时前
Rust 序列化技术全解析:从基础到实战
开发语言·c++·spring boot·vscode·后端·中间件·rust
二川bro5 小时前
第25节:VR基础与WebXR API入门
前端·3d·vr·threejs