C++中的函数指针与宏函数总结

来源:互联网 发布:商用的数据挖掘软件系 编辑:程序博客网 时间:2024/05/29 04:46

1、函数指针

今天看项目代码才发现,函数指针分两种:普通函数指针,类成员函数指针。
那这两中函数指针的定义方法是不一样的。

1.1、普通函数指针

typedef void (*Dfun) (float, int);//(*Dfun) 实际上是(::*Dfun)  也就是全局的意思// Dfun 指向  接受两个输入参数:float,int 的返回值为void类型的函数

1.2、类成员函数指针

由于类的所有成员(包括成员函数)都有一个this指针。因此,必须说明是哪个对象成员函数。

class NameDet;typedef void (NameDet::*Dfun) (float, int);// Dfun 指向NameDet类的成员函数,这种成员函数接受float,int类型作为输入, 返回值类型为void

1.3、如何使用?

一般定义函数指针式为了实现多态。也就是说有很多个输入类型(float,int),返回值类型为void的函数,但是功能不一样。

//因此定义一个map(Caffe中这么做的)  typedef std::map<std::string, BrewFunction> BrewMap;BrewMap g_brew_map;g_brew_map[#func] = &func;  // # 作用:Stringfication//或者是定义一个vector(流水线处理)std::vector<std::pair<std::string, RegFun> > BrewMap;BrewMap.push_back(std::make_pair("xxx",&func))

2、宏函数

在读Caffe源码时候发现很多宏函数
为什么要用宏函数?用普通函数不好么?既然存在必定有其道理。下面分析一下。

2.1Caffe 经典代码

typedef int (*BrewFunction)();typedef std::map<caffe::string, BrewFunction> BrewMap;BrewMap g_brew_map;#define RegisterBrewFunction(func) \namespace { \                                class __Registerer_##func { \ public: /* NOLINT */ \  __Registerer_##func() { \    g_brew_map[#func] = &func; \  } \}; \__Registerer_##func g_registerer_##func; \}// 这里说一下namespace 后面没有接名字:无名命名空间。 在使用时无需前导名字的限定(Caffe:: 或者 std::)// 其实质相当于static定义的局部类(只能在本文件内调用)。当前的C++标准是不推荐使用无名的命名空间的。

2.2 宏函数有什么好处呢?

#define MAX( a, b) ( (a) > (b) (a) : (b) )  //宏函数int max( int a, int b){                     //普通函数  return (a > b a : b)}上述宏函数 vs 普通函数 // 函数调用会带来额外的开销,开辟一片栈空间,记录返回地址,将形参压栈,从函数返回还要释放堆栈。// 宏与类型无关:MAX可以用于float,double,int,甚至是类等一切支持">"运算符的操作// 但是max却不可以。

开辟n个type类型的空间(type类型未知)。

#define MALLOC(n, type) \  ( (type *) malloc((n)* sizeof(type)))//这是普通函数做不到的

注意:仅是简短的函数或者log函数会定义宏。否则,代码量会非常大。
[下面是我经常用到的宏函数]

#define THICKNESS 2#define LINETYPE 5#define DRAW_RECT_ON_IMAGE(IMAGE, RECT, NAME) \{ \    cv::rectangle(IMAGE, RECT, cv::Scalar(0,0,255), THICKNESS, LINETYPE); \    cv::imshow(#NAME, IMAGE); \    cv::waitKey(0); \}
原创粉丝点击