C++回调函数、静态函数、成员函数踩过的坑。

C++回调函数、静态函数、成员函数踩过的坑。

明确一点即回调函数须要是静态函数。缘由:编程

  • 普通的C++成员函数都隐含了一个this指针做为参数,这样使得回调函数的参数和成员函数参数个数不匹配。

若不想使用C式函数做为回调函数呢?(破坏封装性)函数

解决方法

  • 使用static修饰成员函数。static不含this指针。
  • 不用static修饰的成员函数,须要借助中间变量来访问。这个演示的很好。
  • 也能够在回调函数中增长一个变量,类型为该类的类型,做为this指针的传递。

下面讲解一下第二点,我认为比较好用。this

class A 
{
public:
    static void staticmember(){cout<<"static"<<endl;}   //static member
    void nonstatic(){cout<<"nonstatic"<<endl;}          //nonstatic member
    virtual void virtualmember(){cout<<"virtual"<<endl;};//virtual member
};
int main()
{
    A a;
    //static成员函数,取得的是该函数在内存中的实际地址,并且由于static成员是全局的,因此不能用A::限定符
    void (*ptrstatic)() = &A::staticmember;      
    //nonstatic成员函数 取得的是该函数在内存中的实际地址     
    void (A::*ptrnonstatic)() = &A::nonstatic;
    //虚函数取得的是虚函数表中的偏移值,这样能够保证能过指针调用时一样的多态效果
    void (A::*ptrvirtual)() = &A::virtualmember;
    //函数指针的使用方式
    ptrstatic();
    (a.*ptrnonstatic)();
    (a.*ptrvirtual)();
}

直接用类名引出非静态成员函数,赋值给函数指针:.net

//nonstatic成员函数 取得的是该函数在内存中的实际地址     
void (A::*ptrnonstatic)() = &A::nonstatic;

随后须要运行回调函数的时候,使用一个辅助变量来运行,格式为:(变量名. * 函数指针)(参数)指针

(a.*ptrnonstatic)();

应用:类中成员函数的函数指针写法

若是在咱们的编程过程当中:code

  1. 须要使用到回调函数。
  2. 回调函数是一个类的成员函数。
  3. 此成员函数不是静态函数,也不适合作静态函数。

咱们可使用:blog

bool (DoTask::*function)(void *arg);

其中DoTask是一个类名,上面写的就是一个返回值为bool类型,参数为void *类型的函数指针,指向DoTask这个类中的成员函数。内存

而后调用的时候咱们能够:作用域

Dotask d;
//注意ReadData函数不用加括号,要加做用域和地址符
bool (DoTask::*function)(void *arg) = &DoTask::ReadData;
(d.*function)(NULL);

注意点就是赋值给函数指针的时候须要取地址符、加做用域、函数不加括号,直接函数名便可。get

调用的时候,用一个实例去调用函数指针便可。

其它

假如咱们将函数指针放在一个结构体中:

struct task
{
    bool (DoTask::*function)(void *arg);
    void *arg;
};

那么咱们调用它的时候也是同样的。

struct task t;
t.function = &DoTask::ReadData;
...
DoTask d;
(d.*(t.function))(NULL);    //完成调用。

如今看调用这一步。参照上面的:

(d.*function)(NULL)

只不过function如今存在结构体中,替换成从结构体中取出来便可:

function 替换成 t.function

代入便可。

相关文章
相关标签/搜索