回调函数必须要用static的原因

在之前的一篇回调函数简单例子中就写了一个简单的回调小例子,这里补充一下。

一个对象的this指针并不是对象本身的一部分,不会影响sizeof(对象)的结果。this作用域是在类内部,当在类的非静态成员函数中访问类的非静态成员的时候,编译器会自动将对象本身的地址作为一个隐含参数传递给函数。也就是说,即使你没有写上this指针,编译器在编译的时候也是加上this的,它作为非静态成员函数的隐含形参,对各成员的访问均通过this进行。

为了实现回调,我们必须把this指针给转换掉!可为了在该函数中可以直接操作该类中的成员,我们必须保留this指针!所以这是矛盾的。

在类封装回调函数:

 a.回调函数只能是全局的或是静态的。
 b.全局函数会破坏类的封装性,故不予采用。
 c.静态函数只能访问类的静态成员,不能访问类中非静态成员

让静态函数访问类的非静态成员的方法:

在消息回调的函数参数中传递一个该类的指针即可,就像类中创建一个多线程的回调一样.将类的指针传递给该回调函数,然后用该指针调用类的非静态成员函数和指针.或者用一个类的全局指针数组,保存每一个创建出来的类的this指针,用全局指针去调用。如下:

 class A()

回调函数中访问非静态成员

  由于回调函数往往有固定定义,并不接受  A * pThis 参数
   如:CALLBACK MyTimerProc(HWND hwnd,UINT uMsg,UINT idEvent,DWORD dwTime);
【解决方案1】:本方案当遇到有多个类实例对象时会有问题。原因是pThis指针只能指向一个对象。
  class A()
  {
      static void a(); //静态回调函数
      void b();  //非静态函数 
      static A * pThis;   //静态对象指针
  }  
  
  A * A::pThis=NULL;  //这句话必须要在cpp一开始就写,不然编译会报无法解析的外部符号的错。
  A::A()   //构造函数中将this指针赋给pThis,使得回调函数能通过pThis指针访问本对象
  {
       pThis=this;
  }
  void A::a()
  {
      if (pThis==NULL) return;
      pThis->b(); //回调函数中调用非静态函数 
  }
【解决方案2】:本方案解决多个类实例对象时方案1的问题。用映射表存所有对象地址,每个对象保存自己的ID号。
  typedef CMap<UINT,UINT,A*,A*> CAMap;
  class A()
  {
      static void a(); //静态回调函数
      void b();  //非静态函数 
      int m_ID;  //本对象在列表中的ID号
      static int m_SID;   //静态当前对象ID        (需要时,将m_ID赋值给m_SID以起到调用本对象函数的功能)
      static CAMap m_Map; //静态对象映射表
  }  
  
  CAMap A::m_Map;
  int   A::m_SID=0;
  
 
  A::A()   //构造函数中将this指针赋给pThis,使得回调函数能通过pThis指针访问本对象
  {
      if(m_Map.IsEmpty())
      {
   m_ID=1;
      }
      else
      { 
        m_ID=m_Map.GetCount()+1;
      }
      m_Map.SetAt( m_ID, this );
  }
 void A::a()
  {
      if (m_Map.IsEmpty()) return;
      A * pThis=NULL;
      if(m_Map.Lookup(m_SID,pThis))
      {
   pThis->b(); //回调函数中调用非静态函数 
      };
  }
 

原文连接:https://blog.csdn.net/u012072012/article/details/45537387

  • 4
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 在Qt中,回调函数是一种常见的编程技术,用于在特定事件发生时执行特定的代码逻辑。Qt中的回调函数可以使用静态函数实现。 静态函数是类的成员函数,但不需要通过类的实例来调用。使用静态函数作为回调函数的好处是,它们可以直接从类外部访问,无需实例化类对象即可调用。 使用静态函数作为回调函数时,需要满足以下条件: 1. 回调函数必须静态函数,即使用static关键字进行声明。 2. 回调函数的参数列表和返回值类型必须回调接口的定义一致。例如,如果回调接口要求函数指针(或者使用Qt的信号槽机制),则回调函数的参数列表和返回值类型必须与该函数指针(或者信号槽)的类型一致。 3. 在需要注册回调函数的地方(例如,在连接信号与槽时或者设置函数指针时),使用类名加上静态函数名来引用回调函数静态回调函数的一个常见应用场景是在Qt的信号槽机制中。当一个信号被触发时,可以使用静态函数作为槽函数来处理信号。这样的好处是,静态函数无需实例化类对象,可以直接在类外部进行使用。 需要注意的是,在使用静态函数作为回调函数时,由于无法访问实例的非静态成员变量和成员函数,需要确保回调函数的逻辑是独立的,不依赖于实例的状态。 总之,Qt中使用静态函数作为回调函数是一种方便而常见的做法。它们能够简化代码结构,提高代码的可读性和可维护性。同时,通过合理的设计,还能充分发挥Qt框架的优势,并使得代码更加灵活和可扩展。 ### 回答2: 在Qt中,回调函数是一种事件处理机制,用于处理特定的事件或动作。而静态回调函数是指其函数成员属于一个类,不依赖于类的实例对象,可以被类的所有实例对象所共享。 使用静态回调函数的主要好处是不需要创建类的实例对象即可调用回调函数。这在某些场景下非常有用,例如在多线程或跨模块调用中。 在Qt中,可以使用静态函数作为回调函数的方式有两种: 1. 静态成员函数:在类的定义中,将回调函数声明为静态成员函数。例如: ```cpp class MyClass { public: static void myCallbackFunction(int arg); }; void MyClass::myCallbackFunction(int arg) { // 处理回调函数逻辑 } ``` 可以使用类名调用静态回调函数: ```cpp MyClass::myCallbackFunction(100); ``` 2. 普通函数:将普通的非成员函数定义为静态回调函数。例如: ```cpp static void myCallbackFunction(int arg) { // 处理回调函数逻辑 } ``` 可以直接调用该静态回调函数: ```cpp myCallbackFunction(100); ``` 无论是使用静态成员函数还是普通函数作为静态回调函数,都需要注意到静态回调函数无法直接访问类的非静态成员变量和非静态成员函数,因为静态函数不依赖于类的实例对象。如果需要在静态回调函数中访问类的非静态成员,可以将类的实例对象作为参数传递给静态回调函数。 总之,静态回调函数在Qt中是一种非常有用的事件处理机制,可以提供灵活性和代码重用性。 ### 回答3: Qt中的回调函数是一种常用的编程技术,用于在某个特定事件发生时自动调用指定的函数回调函数通常用于处理用户输入、网络请求、异步操作等需要等待事件完成后再进行下一步操作的情况。 在Qt中,回调函数可以定义为静态函数(static function)。静态函数是一种不依赖于对象实例的函数,它属于类而不属于任何对象。定义为静态函数回调函数,具有以下特点: 1. 静态函数在类加载时就被分配内存,不需要通过对象进行调用; 2. 静态函数不能访问非静态的成员变量,只能访问静态成员变量; 3. 静态函数不能使用this指针,因为this指针指向对象实例,而静态函数不依赖于对象实例。 在Qt中使用静态函数作为回调函数的好处是可以避免创建对象实例的开销,提高程序的效率和性能。同时,静态函数可以直接通过类名调用,更加简洁和直观。 以下是一个使用静态函数作为回调函数的示例: class MyClass : public QObject { Q_OBJECT public: static void myCallbackFunction() { // 处理回调函数的逻辑 } }; 在这个示例中,myCallbackFunction()函数定义为静态函数。当需要在某个事件触发时调用该函数时,可以直接使用类名调用: MyClass::myCallbackFunction(); 通过将回调函数定义为静态函数,我们可以方便地在Qt中实现各种事件的处理和回调操作。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值