【C++】灵活使用C/C++宏定义

原创 2016年05月31日 20:36:45

灵活使用C/C++宏定义

 #define宏定义在C语言中有广泛使用。对于C++语言,《Effective C++》第二章告诉我们,在C++中尽量用const、enum、inline替换#define,可以避免很多陷阱。其中const用于定义常量,enum用于定义枚举,inline用于定义内联函数。
 尽管《Effective C++》第二章指出#define宏定义的诸多陷阱,这不代表作者不希望我们使用#define。#define的作用是,在预编译阶段,编译器将#define定义的代码段替换到使用相应宏定义的位置上去,相当于直接将代码替换宏,如果宏定义是安全的、简单的,那么#define宏定义会有很大的作用。很多著名C++第三方库使用了大量的宏定义,可以说明这一点。
 来看看Eigen矩阵库。Eigen是基于模板的C++开源矩阵库,使用或者支持Eigen的知名项目有Google的TensorFlow、Point Cloud Library、OpenCV等。Eigen运用了大量的模板,为了管理这些模板,Eigen使用了大量的宏,我摘要一段如下,其中##符号表示连接两个字符串:

#define EIGEN_MAKE_TYPEDEFS(Type, TypeSuffix, Size, SizeSuffix)   \
typedef Matrix<Type, Size, Size> Matrix##SizeSuffix##TypeSuffix;  \
...
#define EIGEN_MAKE_TYPEDEFS_ALL_SIZES(Type, TypeSuffix) \
EIGEN_MAKE_TYPEDEFS(Type, TypeSuffix, 2, 2) \
EIGEN_MAKE_TYPEDEFS(Type, TypeSuffix, 3, 3) \
...
EIGEN_MAKE_TYPEDEFS_ALL_SIZES(int,                  i)
EIGEN_MAKE_TYPEDEFS_ALL_SIZES(float,                f)
...

上述写出的宏定义代码,定义了

Matrix2i<->Matrix<int, 2, 2>;
Matrix2f<->Matrix<float, 2, 2>;
Matrix3i<->Matrix<int, 3, 3>;
Matrix3f<->Matrix<float, 3, 3>

四个数据类型。用上述宏定义的方法可以用很少的代码,扩展定义更多的类型。
 再来看看VTK。我展示VTK用于定义set/get函数的代码:

//宏定义
#define vtkSetMacro(name,type) \
virtual void Set##name (type _arg) \
  { \
  vtkDebugMacro(<< this->GetClassName() << " (" << this << "): setting " #name " to " << _arg); \
  if (this->name != _arg) \
    { \
    this->name = _arg; \
    this->Modified(); \
    } \
  } 
#define vtkGetMacro(name,type) \
virtual type Get##name () { \
  vtkDebugMacro(<< this->GetClassName() << " (" << this << "): returning " << #name " of " << this->name ); \
  return this->name; \
  } 
  //定义set/get函数
  vtkSetMacro(CurrentCursor,int);
  vtkGetMacro(CurrentCursor,int);

上述代码很方便地定义了
virtual void SetCurrentCursor(int _arg);
virtual int GetCurrentCursor();

这就免得我再去手写一大堆代码。可见宏定义用于定义是很方便的。
另外我附上如果根据操作系统宏来定义不同数据的示例代码:
#ifdef _WIN32
#define SMARTPOINTER(type) std::tr1::shared_ptr<type> SP;
#else
#define SMARTPOINTER(type) std::shared_ptr<type> SP;
#endif
//下面的代码编译错误
//#define SMARTPOINTER(type) \
//#ifdef _WIN32 #define std::tr1::shared_ptr<type> SPA; \
//#else #define std::shared_ptr<type> SPA; #endif

这里看出,如果#define内部还有复杂的宏命令,则编译器很难给出正确的编译结果。尤其是使用旧版本编译器,必须要注意宏定义不能过于复杂。

版权声明:本文为博主原创文章,未经博主允许不得转载。

[cpp]C++中的宏定义

1.不带参数的宏定义:        宏定义又称为宏代换、宏替换,简称“宏”。   格式:   #define 标识符 字符串   其中的标识符就是所谓的符号常量,也称为“宏名...
  • cn_wk
  • cn_wk
  • 2017年02月15日 20:11
  • 1230

C/C++常用宏定义,注意事项,宏中#和##的用法

总结下宏和函数的不同之处,以供大家写代码时使用,这段总结摘自《C和指针》一书。 当然宏定义非常重要的,它可以帮助我们防止出错,提高代码的可移植性和可读性等。 下面列举一些成熟软...
  • anye3000
  • anye3000
  • 2011年08月10日 17:30
  • 4442

C/C++ 宏定义中#、##、#@的区别

#表示:对应变量字符串化   ##表示:把宏参数名与宏定义代码序列中的标识符连接在一起,形成一个新的标识符 连接符#@:它将单字符标记符变换为单字符,即加单引号。例如: #define B(x)...
  • hellokandy
  • hellokandy
  • 2016年01月27日 11:26
  • 4909

Makefile中用宏定义进行条件编译(gcc -D)/在Makefile中进行宏定义-D

在源代码里面如果这样是定义的: #ifdef   MACRONAME //可选代码 #endif 那在makefile里面 gcc   -D   MACRONAME=MACRODEF 或者...
  • maopig
  • maopig
  • 2012年02月03日 09:49
  • 30269

Linux学习笔记——例说makefile 增加宏定义

从学习C语言开始就慢慢开始接触makefile,查阅了很多的makefile的资料但总感觉没有真正掌握makefile,如果自己动手写一个makefile总觉得非常吃力。所以特意借助博客总结makef...
  • xukai871105
  • xukai871105
  • 2014年07月05日 20:37
  • 21968

在Makefile中进行宏定义-D

关键词: Make宏定义 Make传递宏定义 Makefile中添加宏定义 Makefile -D 在Makefile中我们可以通过宏定义来控制源程序的编译。只要在Makefile中的CFLAG...
  • NOHACKCCC
  • NOHACKCCC
  • 2014年02月28日 10:15
  • 2890

Makefile中用宏定义进行条件编译

在源代码里面如果这样是定义的: #ifdef   MACRONAME //可选代码 #endif 那在makefile里面 gcc   -D   MACRONAME=MACRODEF 或者...
  • gdutliuyun827
  • gdutliuyun827
  • 2013年12月13日 09:20
  • 6038

c++ 用宏定义一个函数

#define MAX(a,b) ((a)>(b)?(a):(b))要点:变量都用括号括起来,防止出错,结尾不需要;。在实际编程中,不推荐把复杂的函数使用宏,不容易调试。多行用\#define CRE...
  • fox64194167
  • fox64194167
  • 2015年09月22日 11:20
  • 6503

C++ 语言宏定义函数的使用(定义单行和多行)

昨天笔试问的,不会….. 在软件开发过程中,经常有一些常用或者通用的功能或者代码段,这些功能既可以写成函数,也可以封装成为宏定义。那么究竟是用函数好,还是宏定义好?这就要求我们对二者进行合理的取舍。宏...
  • u012851419
  • u012851419
  • 2016年04月25日 15:54
  • 2995

C++中宏定义和内联函数区别

1. 宏代码不是函数
  • cgl1079743846
  • cgl1079743846
  • 2014年05月27日 00:45
  • 2330
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:【C++】灵活使用C/C++宏定义
举报原因:
原因补充:

(最多只允许输入30个字)