把C++类成员方法直接作为线程回调函数

原创 2013年12月03日 16:43:40

1)运算符 ->* 和.*

这两个运算符 平时很不常用。而且在项目中看到也容易忽视。他们是可以绑定this指针的运算符,看下面的例子:


class CA
{
public:
    int m_i0;
    void m_f0( int value)
    {
        m_i0 = value;
        std::cout << "<<m_f0>> argv=" << value << std::endl;
    }
private:
    int m_i1;
    void m_f1(int value)
    {
        m_i1 = value;
        std::cout << "<<m_f1>> argv=" << value << std::endl;
    }
};


typedef void (CA::*F0)(int);

int main(int c, char *v[])
{
    CA a;
    a.m_i0 = 9;
    int CA::*pm = &CA::m_i0;
    a.*pm = 100;
    
    /*
    int CA::*pr = &CA::m_i1;
    a.*pr = 100;
    错误	1	error C2248 : “CA::m_i1” : 无法访问 private 成员(在“CA”类中声明)
    */

    F0 func = &CA::m_f0;
    (a.*func) (100);

    /*F0 func = &CA::m_f1;*/

    return 0;
}
可以自己运行下 体会下。这个方法是可以 绑定成员函数指针作为回调的,前提是你需要有完整的实例类。


2)奇技淫巧

我以前写线程时要么老老实实照着声明写,要么使用C++类的静态成员函数来作为回调函数,经常会因为线程代码而破坏封装.之前虽然知道类成员函数的展开形式,但从没想过利用过它,昨天看深入ATL时无意中学会了这一招:)

  类成员方法是一个比较特殊的函数,它在编译时会被转化成普通函数,比如有TMyClass类:

class TMyClass
{
    void Func();
};


这个TMyClass::Func最终会转化成 void Func(TMyClass *this); 也就是说在原第一个参数前插入指向对象本身的this指针。

  我们可以利用这个特性写一个非静态类成员方法来直接作为线程回调函数,先看_beginthread函数的定义:

  unsigned long _RTLENTRY _EXPFUNC _beginthread (void (_USERENTRY *__start)(void *),unsigned __stksize, void *__arg);

  其中的第一个参数就是作为线程执行主体的回调函数。它的原型是:void Func(void *),这个void*参数是作为自定义数据传入的。对比一下上面所说的TMyClass::Func的最终形式,它正好可以符合这里的要求。

  现在做个实验:

#include <stdio.h>
#include <process.h>

class TMyClass

{
    int m_nCount;
    int m_nId;
public:
    TMyClass(int nId,int nCount)
        :m_nId(nId),m_nCount(nCount)
    { }

    void _USERENTRY ThreadProc()            // 类成员方法
    {
        for(int i=0; i<m_nCount; i++)       // 根据m_nCount成员打印一排数字
        {
            printf("Class%d : %d\n",m_nId,i);
        }
    }
};

int main(int argc, char* argv[])
{

// 联合类,用于转换类成员方法指针到普通函数指针(试过编译器不允许在这两种函数之间强制转换),不知道有没有更好的方法。

    union { 
        void (_USERENTRY *ThreadProc)(void *);
        void (_USERENTRY TMyClass::*MemberProc)();
    } Proc;     // 尽管联合里的两种函数类型现在看起来有很大不同,但它们的最终形式是相同的。

 


    TMyClass MyClass1(1,10),MyClass2(2,5); // 产生两个TMyClass对象

    Proc.MemberProc = &TMyClass::ThreadProc;   // 转换,Proc.ThreadProc就是对应的普通函数指针了

    _beginthread(Proc.ThreadProc,4096,&MyClass1);   // 开始线程,这里的Proc.ThreadProc实际上是TMyClass::ThreadProc, 它要的this指针是我们给的&MyClass1。
    _beginthread(Proc.ThreadProc,4096,&MyClass2);
    system("pause");
    return 0;
}

运行!神奇吧?:-)

  其实不止线程回调函数,其实只要是形如Func(void*,...)的回调函数都可以用这种方法直接使用类成员方法。(前提是第一个void*是自定义数据,也就是说它不能有其它功能)。


C++类成员函数作为线程回调函数

C++类成员函数作为回调函数的方法
  • a1009563517
  • a1009563517
  • 2016年07月28日 22:47
  • 1607

把C++类成员方法直接作为线程回调函数

我以前写线程时要么老老实实照着声明写,要么使用C++类的静态成员函数来作为回调函数,经常会因为线程代码而破坏封装.之前虽然知道类成员函数的展开形式,但从没想过利用过它,昨天看深入ATL时无意中学会了这...
  • liuchang5
  • liuchang5
  • 2010年07月30日 09:58
  • 509

把C++类成员方法直接作为线程回调函数[转]

我以前写线程时要么老老实实照着声明写,要么使用C++类的静态成员函数来作为回调函数,经常会因为线程代码而破坏封装.之前虽然知道类成员函数的展开形式,但从没想过利用过它,昨天看深入ATL时无意中学会了这...
  • kamaliang
  • kamaliang
  • 2009年02月15日 04:59
  • 1147

把C++类成员方法直接作为线程回调函数

把C++类成员方法直接作为线程回调函数 原文链接:http://blog.csdn.net/waiting4you/article/details/2000796 我以前写线程时要...
  • killcpp
  • killcpp
  • 2013年09月01日 22:34
  • 479

将类成员函数用做C回调函数

 将类成员函数用做C回调函数 提出问题: 回调函数是基于C编程的Windows SDK的技术,不是针对C++的,程序员可以将一个C函数直接作为回调函数,但是如果试图直接使用C++的成员函数作为回调函数...
  • xylary
  • xylary
  • 2007年04月01日 21:03
  • 7606

C++中类成员函数作为回调函数

回调函数是基于C编程的Windows SDK的技术,不是针对C++的,程序员可以将一个C函数直接作为回调函数,但是如果试图直接使用C++的成员函数作为回调函数将发生错误,甚至编译就不能通过。  普通...
  • u012468214
  • u012468214
  • 2013年11月28日 10:45
  • 15768

C++中类成员函数作为回调函数 [转]

C++中类成员函数作为回调函数 [转] http://blog.csdn.net/this_capslock/article/details/17001003 回调函数是基于C编程...
  • ksn13
  • ksn13
  • 2014年10月28日 11:42
  • 21604

确保线程结束之前,传递给线程回调函数的参数的有效性

最近在写一个我把它称为RemoteMedia的东西。其中,服务端程序要创建一个新的进程完成某些工作。而且,这个进程结束后,服务端还要通知客户端。 我所想到的方法是,创建这个进程后,保存进程的句柄值。为...
  • mayadong7349
  • mayadong7349
  • 2013年08月26日 21:26
  • 1804

从C++类成员函数作为回调函数说起

介绍使用boost.function和boost.bind将类的普通成员函数用于回调机制。以及这种回调机制相比通过虚函数和继承实现回调的优势。...
  • mpforwd
  • mpforwd
  • 2010年07月29日 00:20
  • 4654

函数名作为参数传递 与 回调函数

成员函数名不能作为参数传递,否则会发生错误,因为里面隐藏着一个this 指针      回调函数,就是由你自己写的。你需要调用另外一个函数,而这个函数的其中一个参数,就是你的这个回调函数名。这样...
  • cjjwwss
  • cjjwwss
  • 2014年03月20日 17:43
  • 3234
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:把C++类成员方法直接作为线程回调函数
举报原因:
原因补充:

(最多只允许输入30个字)