• 指向类成员函数的指针(转)


    原文:https://blog.csdn.net/jinjinClouded/article/details/5189540?depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-2&utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-2

     参考:

    https://blog.csdn.net/weixin_34107955/article/details/94019091

    https://www.cnblogs.com/zhoug2020/p/11394408.html

    https://www.arduino.cn/thread-42263-1-1.html

          最近在开发中用到了函数指针,于是想整理了一下有关函数指针的概念。O(∩_∩)O~

         首先 函数指针是指向一组同类型的函数的指针;而类成员函数我们也可以相似的认为,它是指向同类中同一组类型的成员函数的指针,当然这里的成员函数更准确的讲应该是指非静态的成员函数。前者是直接指向函数地址的,而后者我们从字面上也可以知道 它肯定是跟类和对象有着关系的。

         函数指针实例:

    typedef int (*p)(int,int);//定义一个接受两个int型且返回int型变量的函数指针类型
    int func(int x,int y)
    {
     printf("func:x=%d,y=%d/n",x,y);
     return (x<y?x:y);
    }
    
    int main()
    {
     p fun=func;//定义函数指针并给它赋上一个函数指针
     cout<<"min:"<<(*fun)(4,5)<<endl;//为什么*fun需要用()扩起来呢?因为*的运算符优先级比()低,如果不用()就成了*(fun())
     return 0;
    }
    
       而“指向类成员函数的指针”却多了一个类的区别:
    
    class A
    {
    public:
     int func(int x,int y)
     {
      printf("A::func:x=%d,y=%d/n",x,y);
      return (x<y?x:y);
     }
    };
    typedef int (A::*p)(int,int);//指针名前一定要加上所属类型类名 A::的限定
    
    int main()
    {
     p fun=&A::func;
     A a;                  //因为成员函数地址的解引用必须要附驻与某个对象的地址,所以我们必须创建某个对象。
     cout<<"min:"<<(a.*fun)(4,5)<<endl;
     return 0;
    }
    
    

     

    嘿嘿。。只是用起来 .*  感觉怪怪滴。

    接下来 我们可以再扩展一下下:

    #include <tchar.h>
    #include <iostream>
    #include <stdio.h>
    using namespace std;
    
    
    class A
    {
    public:
     int func1(int x,int y)
     {
      printf("A::func:x=%d,y=%d/n",x,y);
      return (x<y?x:y);
     }
     virtual int func2(int x,int y)
     {
      printf("A::func:x=%d,y=%d/n",x,y);
      return (x>y?x:y);
     }
    };
    class B:public A
    {
    public:
     virtual int func2(int x,int y)
     {
      printf("B::func:x=%d,y=%d/n",x,y);
      return (x+y);
     }
    
    };
    typedef int (A::*p)(int,int);//指针名前一定要加上所属类型类名 A::的限定
    typedef int (B::*p0)(int,int);
    
    int main()
    {
     A a;                   //因为成员函数地址的解引用必须要附驻与某个对象的地址,所以我们必须创建某个对象。
     B b;
     p fun=&A::func1;
    
     cout<<(a.*fun)(4,5)<<endl;
     cout<<(b.*fun)(4,5)<<endl<<endl;
    
     fun=&A::func2;
     cout<<(a.*fun)(4,5)<<endl;//请注意这里调用的是虚函数,嘿嘿 还真神奇 类成员函数指针也支持多态。
     cout<<(b.*fun)(4,5)<<endl<<endl;
    
    
     //fun=&B::func2;         //这样式错误滴,因为不存在派生类的"指向类成员函数的指针"到基类的"指向类成员函数的指针"的隐式转换
     fun=(int (A::*)(int,int))&B::func2;//应该进行强制转换
     cout<<(a.*fun)(4,5)<<endl;
     cout<<(b.*fun)(4,5)<<endl<<endl;
     
     p0 fun0=&B::func2;
     cout<<(a.*fun)(4,5)<<endl;
     cout<<(b.*fun)(4,5)<<endl<<endl;
     
     fun0=&A::func2;           //正确,因为这里进行了隐式转换
     cout<<(a.*fun)(4,5)<<endl;
     cout<<(b.*fun)(4,5)<<endl<<endl;
     //从上面我们不难发现 指向类成员函数的指针基类和派生类的关系和指向类对象的指针基类和派生类的关系完全相反,
     //基类成员函数的布局被认为是派生类成员函数布局的一个子集
     return 0;
    }

    运行结果:

    A::func:x=4,y=5/n4
    A::func:x=4,y=5/n4
    
    A::func:x=4,y=5/n5
    B::func:x=4,y=5/n9
    
    A::func:x=4,y=5/n5
    B::func:x=4,y=5/n9
    
    A::func:x=4,y=5/n5
    B::func:x=4,y=5/n9
    
    A::func:x=4,y=5/n5
    B::func:x=4,y=5/n9
    

      

    接下  是有关模板类的类成员函数指针的使用

    实例如下:

    #include <tchar.h>
    #include <iostream>
    #include <stdio.h>
    using namespace std;
    
    
    class A
    {
    public:
     int func(int x,int y)
     {
      printf("A::func : x=%d,y=%d/n",x,y);
      return (x<y?x:y);
     }
    };
    class B
    {
    public:
     int func(int x,int y)
     {
      printf("B::func : x=%d,y=%d/n",x,y);
      return (x>y?x:y);
     }
    };
    
    template<class T>
    class C
    {
    public:
     T c;
     void Print()
     {
      int (T::*p)(int,int)=&T::func;
      (c.*p)(4,5);
     }
    };
    
    int main()
    {
     C<A> ca;
     C<B> cb;
    
     ca.Print();
     cb.Print();
     return 0;
    }

    从上面 可以很清晰地看到。。其实它和普通的模板没有什么区别。。只不过将限定名称该为参数名酒OK啦。。。

    嘿嘿。。。

     

  • 相关阅读:
    《linux 内核全然剖析》 笔记 CODE_SPACE 宏定义分析
    Item 8:析构函数不要抛出异常 Effective C++笔记
    Eclipse经常使用快捷键
    多人即时战斗游戏服务端系列[2]--90坦克Online游戏对象介绍以及渲染机制
    STM8S awu及看门狗IWDG WWDG应用(转)
    使用STM8SF103 ADC采样电压(转)
    BHS-STM32工具系列
    STM32 FLASH模拟EEPROM 使用和优化(转)
    STM32+NRF24L01无线(转)
    像51一样操作STM32的IO(转)
  • 原文地址:https://www.cnblogs.com/lh03061238/p/12693455.html
Copyright © 2020-2023  润新知