C++ 中宏(macro)#,##,和...(可变参数宏variadic macros)

来源:互联网 发布:淘宝量子恒道统计 编辑:程序博客网 时间:2024/06/06 01:22
#是将传入的变量字符串化

#define PRINTCLASS(ClassName) printout(#ClassName)

在宏中入在是一个类名,但函数printout需要传入的参数是一个字符串,这时候就需要把传入的变量 转化成字符串。

PRINTCLASS(ClassName);

相当于:

printout("ClassName");

## 在宏中是连接两个单元
有时候定义一个变量,这个变量的名字要由外面输入,这时候就需要宏的##。

#define DeclareSomething(ArgumentName,i) int ArgumentName##i

DeclareSomething(rr,4);

就相当于:

int rr4;

##可以连连接两个宏,也可连接宏和其它任意

#define DeclareSomething(ArgumentName) int ArgumentName##index

DeclareSomething(rr);

相当于:

int rrindex;

或是这样,##后面是宏的变量 :

#define DeclareSomething(ArgumentName) int index##ArgumentName
DeclareSomething(rr);

相当于:

int indexrr;

##还有其它作用,下面会有描述。 
...是可变参数宏

 #define Declare_Fun(...) typedef std::function<void(__VA_ARGS__)> iStdFunction

这里定义了一个可变参数宏,用它来定义一个返回类型是void,参数个数不定的std::function

Declare_Fun(int,int,double);

展开后会是:

std::function<void(int,int,double)> iStdFunction;

另一种情况,当定义的std::function,第一个参数已经固定了,后面带多少参数不确定。

#define Declare_Fun(...) typedef std::function<void(int,##__VA_ARGS__)> iStdFunction
Declare_Fun(float,double)

 展开会是:

std::function<void(int,float,double)> iStdFunction

如果在宏里不写任何参数:

Declare_Fun();

 展开会是:

std::function<void(int)> iStdFunction;

 注意##的作用,当没有参数传入时,也可以将第一个参数后面的逗号在展开时去掉。
 在用宏写一些复杂的语句时,最好用g++预编译先展开看看与自己想象的是不是一样。
 预编译的方式如下 :

gcc -E m.cpp -o m.i

 其中 -E代表预编译,m.cpp是要预编译的文件,m.i是生成的目标文件,预编译完成后打开m.i。里面已经展开了所有的宏,再对比是不自己想要的结果,如果不是,去修改原文件就行了。


c++利用宏可以实现很多实用的东西,但是在这之前首先要了解宏的上述用法。宏其实是非常简单的东西,大家第一次用宏估计就是类似#define PI 3.14,但正是因为它的简单,可以它的扩展性和利用性告别强,以至于有千变万化的感觉。估计宏在最初设计的时候,也没有想过要实现这些看上去很奇葩的东西和封装。尤其是写框架的时候,有时候需要给其它开发人员提供一些接口,用宏封装可以使接口变得很清晰简单。
原创粉丝点击