宏、宏定义
文章目录
- 一、定义
- 二、宏的使用
- 1.是或否
- 2.二选一
- (1)区分操作系统的宏命令
- 2.防止头文件重复包含的宏命令 (对于.h文件)
- 三、必须使用宏的场景
- 场景一:条件编译(跨平台 操作系统 / 开关)
- 场景二:日志记录(获取文件名、行号、函数名)
- 场景三:Qt 框架的特殊情况(对你很重要)
一、定义
1.在文件开头定义宏
#define宏名 宏值举例:
#definePI3.14159#defineMAX_SIZE100#defineENABLE_DEBUG// 常用于条件编译(配合 #ifdef)2.在某头文件里定义宏,然后在文件头部#include "定义宏的头文件.h"
例如,在version.h里写上:
#defineUOS_CMBC1//0:标准版本 1:民生银行UOS版本然后在其他.h或.cpp文件头部写上
#include"version.h"二、宏的使用
1.是或否
#if宏//或者#if !宏内容#endif举例:
#include<iostream>// 这行就像“打开开关”。如果把这行注释掉,开关就关了。#defineENABLE_DEBUGintmain(){inta=10;#ifdefENABLE_DEBUG// 如果上面定义了 ENABLE_DEBUG,这段代码就会被保留并编译std::cout<<"调试信息:变量 a 的值是 "<<a<<std::endl;#endifstd::cout<<"程序继续运行..."<<std::endl;return0;}2.二选一
#ifdef宏//注意,二选一不能出现 #ifdef !宏内容1#else内容2#endif举例:需要跨平台的代码,需要区分Windows和Linux操作系统(区分操作系统的宏不需要自己定义,系统可直接识别)
(1)区分操作系统的宏命令
Windows的宏是WIN32,注意三个字母都要大写,否则无法识别。
#ifdefWIN32Windows代码#elseUnix/Linux代码#endif2.防止头文件重复包含的宏命令 (对于.h文件)
以LogWidget.h为例
方法1:3行搞定,是通用的宏
#ifdefLogWidget_H#defineLogWidget_H内容#endif方法2: 1行搞定,但不通用,仅限某些
#pragmaonce内容三、必须使用宏的场景
坚决不推荐使用(尤其是宏函数),但在极少数特定场景下,它们依然是“不可替代”的。
尽管不推荐,但在以下 3 种场景,宏依然是唯一解,C++ 标准至今没有提供更好的替代品:
场景一:条件编译(跨平台 操作系统 / 开关)
这是你刚刚提到的 #define ENABLE_DEBUG 和 #ifdef _WIN32,强烈推荐使用。
这是预处理器独有的能力,可以在编译前就剔除不兼容平台的代码,这是普通函数做不到的。
场景二:日志记录(获取文件名、行号、函数名)
如果你想打印“当前在哪个文件的哪一行出了错”,必须用宏,因为FILE、LINE、func这些魔法宏是由预处理器在编译时填入的。
// 这种多行宏,业界仍在大量使用(如 spdlog、Qt 的 qDebug)#defineLOG_ERROR(msg)\do{\std::cerr<<"["<<__FILE__<<":"<<__LINE__<<"] "<<msg<<std::endl;\}while(0)场景三:Qt 框架的特殊情况(对你很重要)
Qt 本身大量使用了宏,而且你必须配合它:
signals / slots / emit:这些都是 Qt 定义的宏,MOC(元对象编译器)需要它们来生成反射代码。你不能不用。
Q_OBJECT:这也是宏,用于开启信号槽和属性系统。
区别在于:Qt 的宏大多用于类声明(代码生成),而不是用于数值计算。所以在 Qt 项目中,只要遵循官方规则即可,切勿自己发明复杂的计算宏。
