Chinaunix首页 | 论坛 | 博客
  • 博客访问: 463783
  • 博文数量: 145
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 1060
  • 用 户 组: 普通用户
  • 注册时间: 2013-08-22 11:52
个人简介

专注计算机技术: Linux Android 云计算 虚拟化 网络

文章分类

全部博文(145)

文章存档

2016年(3)

2015年(21)

2014年(75)

2013年(46)

我的朋友

分类: C/C++

2014-10-30 07:51:18

今天看到有人碰到的一个问题与函数指针有关,是个很特殊的问题: C语言写的函数,要在C++的类里面调用,但是C函数有个参数是全局函数指针(callback函数)。貌似 为了代码更加OO化,想将该C函数封装到一个class里面,然后将callback作为参数传入该class,当然原先callback函数对应的功能都要OO化,用class的member function来实现。所以:问有没有将 C++的member function pointer转化为 C的callback函数指针直接使用的方法。 

原来的题目在这里:

其实:C++的函数指针包括三种:  全局函数指针,类的static函数指针和成员函数指针。前两个几乎没有区别,最后一个与前面两个有本质的区别。是完全不同的类型。C++是强类型的语言,所以使用两类指针时,不能直接赋值。先来看一下他们定义和调用的语法吧:

点击(此处)折叠或打开

  1. class C
  2. {
  3. public: int mem_fun(int arg);
  4.      static int static_fun(int arg);
  5. };

  6. int global_fun(int arg);

  7. typedef int (C::*Mem_fun)(int arg);
  8. Mem_fun pmf = &C::mem_fun; // &(C::mem_fun) is error

  9. C ci;
  10. (ci.*pmf)(1); // ci.(*pmf)(1) error; (ci.(*pmf))(1) error;

  11. typedef int (*C_Fun)(int arg);
  12. C_Fun p_static_fun = &C::static_fun;
  13. C_Fun p_global_fun = &global_fun;

C++的member function pointer调用时,需要依赖具体的对象(或指针);而全局函数和类的static函数指针是可以直接调用的,两种指针的基类型完全不同,调用需要的参数也不同,不能转化。

 

贴一下STL的 mem_fun_t  和 mem_fun_ref_t 的实现:


点击(此处)折叠或打开

  1. template <class _Ret, class _Tp>
  2. class mem_fun_t : public unary_function<_Tp*,_Ret>
  3. {
  4.     public:
  5.         explicit mem_fun_t(_Ret (_Tp::*__pf)())
  6.             :_M_f(__pf)
  7.         {
  8.         }
  9.         _Ret operator()(_Tp* __p) const
  10.         {
  11.             return (__p->*_M_f)();
  12.         }
  13.     private:
  14.         _Ret (_Tp::*_M_f)();
  15. };

  16. template <class _Ret, class _Tp>
  17. class mem_fun_ref_t : public unary_function<_Tp,_Ret>
  18. {
  19.     public:
  20.         explicit mem_fun_ref_t(_Ret (_Tp::*__pf)())
  21.             : _M_f(__pf)
  22.         {
  23.         }
  24.         _Ret operator()(_Tp& __r) const
  25.         {
  26.             return (__r.*_M_f)();
  27.         }
  28.     private:
  29.         _Ret (_Tp::*_M_f)();
  30. };

这两个class 是成员函数指针的adapter, 方便泛型算法的调用。从 operator ()的实现中可以明确看出 member function pointer 的使用方法。

 

我给出了一个template的方式,将每个 callback的实现 写成类的static函数,且static函数名称固定。

然后封装C函数的那个类,需要一个template 参数,具体调用C函数的时候的地方,根据template 参数,调用Type::Callback。

 

代码如下:


点击(此处)折叠或打开

  1. #include <iostream>
  2. int sql_exec(const char * sql, int (*callback)(int *))
  3. {
  4.  std::cout << "sql_exec" << std::endl;
  5.  callback(0);
  6. }

  7. class SqlParser
  8. {
  9. public:
  10.     static int Callback(int * p)
  11.     {
  12.         std::cout << "sqlParser::callback" << std::endl;
  13.     }
  14. };

  15. class AddressParser
  16. {
  17. public:
  18.     static int Callback(int * p)
  19.     {
  20.         std::cout << "AddressParser::callback " << std::endl;
  21.      }
  22. };

  23. template<class SqlParser>class SqlCommand
  24. {
  25. public:
  26.     SqlCommand(char * sql, SqlParser parser)
  27.         : m_parser(parser), m_sql(sql)
  28.     {
  29.     }
  30.      int executeQuery()
  31.      {
  32.          std::cout << m_sql << std::endl;
  33.          return sql_exec_cpp(m_sql);
  34.      }
  35. private:
  36.     int sql_exec_cpp(const char * sql)
  37.     {
  38.         return sql_exec(sql, SqlParser::Callback);
  39.      }
  40. private:
  41.     SqlParser m_parser;
  42.     char * m_sql;
  43. }
  44. ;
  45. int main(){
  46.  char * sql = "select * from sqlParser;
  47. ";
  48.  SqlCommand<SqlParser> sqlcmd(sql, SqlParser());
  49.  sqlcmd.executeQuery();
  50.  char * addrSql = "select * from address;
  51. ";
  52.  SqlCommand<AddressParser> addrSqlCmd(addrSql, AddressParser());
  53.  addrSqlCmd.executeQuery();
  54.  return 0;
  55. }




阅读(732) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~