zoukankan      html  css  js  c++  java
  • C++回调函数、静态函数、成员函数踩过的坑。

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

    明确一点即回调函数需要是静态函数。原因:

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

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

    解决方法

    • 使用static修饰成员函数。static不含this指针。
    • 不用static修饰的成员函数,需要借助中间变量来访问。这个演示的很好。
    • 也可以在回调函数中增加一个变量,类型为该类的类型,作为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)();
    }
    

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

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

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

    (a.*ptrnonstatic)();
    

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

    如果在我们的编程过程中:

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

    我们可以使用:

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

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

    然后调用的时候我们可以:

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

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

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

    其它

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

    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
    

    代入即可。

  • 相关阅读:
    Servlet 易错点和注意点
    Spring 完成自动注入(autowire)
    Java 定时调度Timer&Quartz
    常用Linux命令杂记
    Spring 使用AOP——基于注解配置
    Spring 使用AOP——xml配置
    Spring 使用纯注解方式完成IoC
    Spring 简单使用IoC与DI——XML配置
    让多个HTML页面 使用 同一段HTML代码
    Feture、ListenableFuture、ComplatableFuture
  • 原文地址:https://www.cnblogs.com/love-jelly-pig/p/10271669.html
Copyright © 2011-2022 走看看