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