前端学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);
相关推荐
MiyueFE几秒前
告别 addEventListener
前端
MiyueFE5 分钟前
🚀🚀五个前端开发者都应该了解的TS技巧
前端·typescript
gaog2zh27 分钟前
100201组件拆分_编辑器-react-仿低代码平台项目
前端·react.js·编辑器
晓131339 分钟前
JavaScript进阶篇——第八章 原型链、深浅拷贝与原型继承全解析
开发语言·javascript·原型模式
R-G-B1 小时前
【46】MFC入门到精通——MFC显示实时时间,获取系统当前时间GetCurrentTime()、获取本地时间GetLocalTime()
c++·mfc·mfc显示实时时间·mfc获取系统当前时间·getcurrenttime·getlocaltime
鹅毛在路上了1 小时前
CMake-gdb调试,解决LLVM ERROR: out of memory
c++·gdb·llvm
tomly20201 小时前
【小米训练营】C++方向 实践项目 Android Player
android·开发语言·c++·jni
蓝婷儿1 小时前
每天一个前端小知识 Day 33 - 虚拟列表与长列表性能优化实践(Virtual Scroll)
前端·性能优化
还是大剑师兰特1 小时前
CSS面试题及详细答案140道之(41-60)
前端·css·大剑师·css面试·css示例
大专生学编程1 小时前
QT简介和QT环境搭建
c++·qt