C++的 成员函数指针, 静态函数指针,全局函数指针 区别

 

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

原来的题目在这里: http://topic.csdn.net/u/20090914/16/670b5f08-5d61-49df-b0cd-fe6e33f5d0f4.html?38764

 

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

class C
{
public:  int mem_fun(int arg);  
	 static int static_fun(int arg);
};

int global_fun(int arg); 

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

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

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

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

 

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

 

template <class _Ret, class _Tp>
class mem_fun_t : public unary_function<_Tp*,_Ret> 
{
	public: 
		explicit mem_fun_t(_Ret (_Tp::*__pf)()) 
			:_M_f(__pf) 
		{
		}
		_Ret operator()(_Tp* __p) const 
		{
			return (__p->*_M_f)(); 
		}
	private:
		_Ret (_Tp::*_M_f)();
};

template <class _Ret, class _Tp>
class mem_fun_ref_t : public unary_function<_Tp,_Ret> 
{
	public: 
		explicit mem_fun_ref_t(_Ret (_Tp::*__pf)()) 
			: _M_f(__pf) 
		{
		} 
		_Ret operator()(_Tp& __r) const 
		{ 
			return (__r.*_M_f)(); 
		}
	private: 
		_Ret (_Tp::*_M_f)();
}; 


 

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

 

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

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

 

代码如下:

#include <iostream> 
int sql_exec(const char * sql, int (*callback)(int *))
{
 std::cout << "sql_exec" << std::endl;
 callback(0);
}

class SqlParser
{
public: 
	static int Callback(int * p)
	{
		std::cout << "sqlParser::callback" << std::endl;
	}
};

class AddressParser
{
public: 
	static int Callback(int * p)
	{
		std::cout << "AddressParser::callback " << std::endl;
	 }
};

template<class SqlParser>class SqlCommand
{
public: 
	SqlCommand(char * sql, SqlParser parser)
		: m_parser(parser), m_sql(sql)
	{
	}
	 int executeQuery()
	 {
		 std::cout << m_sql << std::endl;
		 return sql_exec_cpp(m_sql);
	 }
private:
	int sql_exec_cpp(const char * sql)
	{
		return sql_exec(sql, SqlParser::Callback);
	 }
private: 
	SqlParser m_parser;
	char * m_sql;
}
;
int main(){
 char * sql = "select * from sqlParser;
";
 SqlCommand<SqlParser> sqlcmd(sql, SqlParser());
 sqlcmd.executeQuery();
 char * addrSql = "select * from address;
";
 SqlCommand<AddressParser> addrSqlCmd(addrSql, AddressParser());
 addrSqlCmd.executeQuery();
 return 0;
}



  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值