第12章 - 预处理器和命名空间
嗨,朋友!我是长安。
这一章我们要学习两个重要概念:预处理器和命名空间。
预处理器在代码编译前处理,而命名空间帮助我们组织和管理代码,避免命名冲突。
🔧 预处理器指令
预处理器在编译之前处理源代码,所有预处理指令都以 # 开头。
#include - 包含头文件
我们一直在使用的 #include就是预处理指令:
#include <iostream> // 包含系统头文件
#include "myfile.h" // 包含自定义头文件
区别:
<>- 在系统目录中查找""- 先在当前目录查找,再在系统目录查找
#define - 定义宏
定义常量
#include <iostream>
using namespace std;
#define PI 3.14159
#define MAX_SIZE 100
int main() {
double radius = 5.0;
double area = PI * radius * radius;
cout << "圆的面积:" << area << endl;
cout << "最大容量:" << MAX_SIZE << endl;
return 0;
}
定义函数宏
#include <iostream>
using namespace std;
#define SQUARE(x) ((x) * (x))
#define MAX(a, b) ((a) > (b) ? (a) : (b))
int main() {
cout << "5的平方:" << SQUARE(5) << endl;
cout << "10和20中较大的:" << MAX(10, 20) << endl;
return 0;
}
注意
宏是简单的文本替换,要小心使用括号避免优先级问题:
#define BAD_SQUARE(x) x * x // ❌ 危险
#define GOOD_SQUARE(x) ((x) * (x)) // ✅ 安全
// BAD_SQUARE(2 + 3) 会被替换成 2 + 3 * 2 + 3 = 11
// GOOD_SQUARE(2 + 3) 会被替换成 ((2 + 3) * (2 + 3)) = 25
#ifdef / #ifndef - 条件编译
#include <iostream>
using namespace std;
#define DEBUG // 定义调试模式
int main() {
int value = 100;
#ifdef DEBUG
cout << "调试信息:value = " << value << endl;
#endif
cout << "程序运行中..." << endl;
return 0;
}
#pragma once - 防止重复包含
// myheader.h
#pragma once
// 或者使用传统方式:
#ifndef MYHEADER_H
#define MYHEADER_H
// 头文件内容
#endif
📦 命名空间
为什么需要命名空间?
想象两个人都叫"张三",在同一个房间会很混乱。命名空间就像给他们加上姓氏:"北京_张三"和"上海_张三"。
// 没有命名空间 - 可能冲突
int value = 10;
int value = 20; // ❌ 错误:重复定义
// 使用命名空间 - 不冲突
namespace A {
int value = 10;
}
namespace B {
int value = 20;
}
定义命名空间
#include <iostream>
using namespace std;
// 定义命名空间
namespace Math {
const double PI = 3.14159;
double square(double x) {
return x * x;
}
}
namespace Physics {
const double G = 9.8; // 重力加速度
double freefall(double t) {
return 0.5 * G * t * t;
}
}
int main() {
cout << "PI = " << Math::PI << endl;
cout << "5的平方 = " << Math::square(5) << endl;
cout << "自由落体2秒的距离 = " << Physics::freefall(2) << endl;
return 0;
}
using 声明
#include <iostream>
using namespace std;
namespace MyNamespace {
int value = 100;
void print() {
cout << "MyNamespace::print()" << endl;
}
}
int main() {
// 方式1:使用完整名称
cout << MyNamespace::value << endl;
// 方式2:using 声明
using MyNamespace::print;
print(); // 可以直接使用
// 方式3:using 指令(不推荐)
using namespace MyNamespace;
cout << value << endl; // 可以直接使用
return 0;
}
建议
- ✅ 在函数内使用
using声明 - ⚠️ 谨慎在全局使用
using namespace - ❌ 头文件中不要使用
using namespace
嵌套命名空间
#include <iostream>
using namespace std;
namespace Company {
namespace HR {
void hire() {
cout << "招聘员工" << endl;
}
}
namespace IT {
void deploy() {
cout << "部署系统" << endl;
}
}
}
// C++17 简化写法
namespace Company::Finance {
void pay() {
cout << "发工资" << endl;
}
}
int main() {
Company::HR::hire();
Company::IT::deploy();
Company::Finance::pay();
return 0;
}
🌟 实战案例
案例1:数学工具库
#include <iostream>
using namespace std;
namespace MathUtils {
const double PI = 3.14159;
const double E = 2.71828;
double power(double base, int exp) {
double result = 1;
for (int i = 0; i < exp; i++) {
result *= base;
}
return result;
}
double abs(double x) {
return x < 0 ? -x : x;
}
}
int main() {
using namespace MathUtils;
cout << "PI = " << PI << endl;
cout << "E = " << E << endl;
cout << "2^10 = " << power(2, 10) << endl;
cout << "|-5| = " << abs(-5) << endl;
return 0;
}
案例2:游戏引擎命名空间
#include <iostream>
#include <string>
using namespace std;
namespace GameEngine {
namespace Graphics {
void draw(const string& obj) {
cout << "绘制: " << obj << endl;
}
}
namespace Audio {
void play(const string& sound) {
cout << "播放: " << sound << endl;
}
}
namespace Physics {
void simulate() {
cout << "物理模拟中..." << endl;
}
}
}
int main() {
GameEngine::Graphics::draw("角色");
GameEngine::Audio::play("背景音乐");
GameEngine::Physics::simulate();
return 0;
}
案例3:版本控制
#include <iostream>
using namespace std;
#define VERSION_MAJOR 2
#define VERSION_MINOR 1
#define VERSION_PATCH 5
namespace App {
void showVersion() {
cout << "版本: " << VERSION_MAJOR << "."
<< VERSION_MINOR << "."
<< VERSION_PATCH << endl;
}
#ifdef DEBUG
void debugInfo() {
cout << "[DEBUG] 调试模式已启用" << endl;
}
#endif
}
int main() {
App::showVersion();
#ifdef DEBUG
App::debugInfo();
#endif
return 0;
}
案例4:平台相关代码
#include <iostream>
using namespace std;
#ifdef _WIN32
#define PLATFORM "Windows"
#elif __APPLE__
#define PLATFORM "macOS"
#elif __linux__
#define PLATFORM "Linux"
#else
#define PLATFORM "Unknown"
#endif
int main() {
cout << "当前平台: " << PLATFORM << endl;
#ifdef _WIN32
cout << "执行 Windows 特定代码" << endl;
#elif __linux__
cout << "执行 Linux 特定代码" << endl;
#endif
return 0;
}
🎯 小结
| 概念 | 说明 | 示例 |
|---|---|---|
| #include | 包含头文件 | #include <iostream> |
| #define | 定义宏 | #define PI 3.14 |
| #ifdef | 条件编译 | #ifdef DEBUG |
| #pragma once | 防止重复包含 | #pragma once |
| namespace | 定义命名空间 | namespace MyNS { } |
| using | 使用命名空间 | using namespace std; |
| :: | 作用域解析符 | std::cout |
重要提醒:
- ✅ 使用
const而不是#define定义常量 - ✅ 在函数内使用
using声明 - ✅ 命名空间可以帮助组织大型项目
- ⚠️ 避免全局使用
using namespace
💪 练习题
- 创建一个工具命名空间,包含常用的字符串处理函数
- 使用宏定义实现简单的断言功能
- 创建嵌套命名空间表示公司组织结构
- 使用条件编译实现调试日志功能
- 创建一个数学库命名空间,包含各种数学函数
点击查看参考答案
题目1 参考答案:
#include <iostream>
#include <string>
using namespace std;
namespace StringUtils {
string toUpper(string str) {
for (char& c : str) {
if (c >= 'a' && c <= 'z') {
c = c - 'a' + 'A';
}
}
return str;
}
string toLower(string str) {
for (char& c : str) {
if (c >= 'A' && c <= 'Z') {
c = c - 'A' + 'a';
}
}
return str;
}
string reverse(string str) {
int left = 0, right = str.length() - 1;
while (left < right) {
swap(str[left], str[right]);
left++;
right--;
}
return str;
}
}
int main() {
using namespace StringUtils;
string text = "Hello World";
cout << "原文: " << text << endl;
cout << "大写: " << toUpper(text) << endl;
cout << "小写: " << toLower(text) << endl;
cout << "反转: " << reverse(text) << endl;
return 0;
}
🎉 恭喜完成进阶基础!
你已经完成了进阶基础的全部内容(第8-12章)!
现在你已经掌握了:
- ✅ 指针和内存管理
- ✅ 引用和动态内存
- ✅ 结构体和枚举
- ✅ 文件操作
- ✅ 预处理器和命名空间
🚀 下一步
接下来,我们要进入 C++ 的核心——面向对象编程!
