手机站
网通分站
电信主站
密 码:
用户名:
当前位置 : 主页>程序设计>C/C++>列表

在单独线程中执行对象成员函数

来源:互联网 作者:west263.com 时间:2008-02-23
西部数码-全国虚拟主机10强!40余项虚拟主机管理功能,全国领先!双线多线虚拟主机南北访问畅通无阻!免费赠送企业邮局,.CN域名,自助建站480元起,免费试用7天,满意再付款! P4主机租用799元/月.月付免压金!
  问题的提出:

  实际上任何线程都是用来处理C函数的,而不是C 类成员函数。标准库中提供一个API函数,这个函数以回调函数指针作为线程的执行代码并在单独的线程中调用回调函数。问题是在这样的线程库中不能创建执行对象成员函数的线程;只能使用普通的函数。因此,下列代码是失败的:

// 启动线程库函数的线程
int thr_create (void (*pf)(), void* prm, thread_t* pth);

#include "class1.h"

int func (void *param )
{
thread_t t1;
// 下列调用导致编译器错误: "Cannot convert ''void (class1::*)()'' to ''void (*)()''"
// 意思是不能转换类型
return thr_create ( &class1::some_method, param, &t1);
}

  函数thr_create()需要回调函数的地址,void* 作为地址参数被传递到回调函数,同时传递的参数更有thread_t变量的指针(有关回调函数和函数指针的概念参见VC知识库中另外的文章)。

  上面的代码之所以编译失败是因为传递到thr_create()的第一个参数是类class1的成员函数指针,而不是普通函数指针。从概念上讲,普通函数和类成员函数是两个完全不同的事情。即使进行强制类型转换也不行。那么如何解决这个问题呢?

  方法一:使用静态成员函数

  第一个解决方法是使回调成员函数为静态。因为静态成员函数不带隐含式参数“this”。因此,能够将其参数中的地址当作是普通函数的指针来使用。假如要从静态成员函数中访问对象的数据成员,显式传入对象的地址即可。例如:

class Hack
{
private:
int x;
public:
int get_x();
static void func(Hack * pthis); // 静态成员函数
void func2(); // 非静态成员函数
};

void Hack::func(Hack * pthis)
{
int y = pthis->get_x(); // 访问对象的数据成员
}

  这个方法在大多数情形下都能行得通,但有时候成员函数不能声明为静态,也就是说成员函数是虚函数或正在使用不能修改的第三方类。碰到这种情况时,用方法一解决问题就比较难了。

  方法二:处理非静态成员函数

  假设需要在单独的线程中调用类Hack的非静态成员函数func2()。不用直接传递成员函数的地址到thr_create(),声明一个带 void* 参数的普通函数intermediary(void*),然后调用他:

void intermediary(void*);

  接着创建一个结构,结构定义如下:

struct A
{
Hack * p; //类对象指针
void (Hack::*pmf)(); // 成员函数指针
};

  创建一个结构实例,用希望的对象地址和成员函数地址填充结构(有关周详的成员函数指针内容请参见VC知识库中的其他文章)。

A a; // 结构实例
Hack h; // 创建对象
//填充结构
a.p = & h;
a.pmf = &Hack::func2; // 取成员函数地址

  现在回过头来实现intermediary()函数:

void intermediary(void* ptr)
{
 A* pa=static_cast < A* > (ptr); // 强制转换 p 为 A*
 Hack* ph=pa->p; // 从A中析取Hack对象地址
 void (Hack::*pmf)()=pa->pmf; // 析取 ptr 到成员函数
 (ph->*pmf)(); // 调用成员函数
}

  最后将intermediary()的地址传递到thr_create():

thr_create (intermediary, (void*) &a, &t1 );

  thr_create()调用函数intermediary()并将A的地址传递给他。intermediary()再从其指针参数中展开结构A并调用希望的成员函数。这种间接方式的处理能够安全地在单独线程中启动成员函数,即便是线程库不支持成员函数。假如需要调用不同类的不同成员函数,能够将结构A转换成类模板,将函数intermediary()转换成函数模板。从而编译器便会自动产生大多数样板文档代码。




文章整理:西部数码--专业提供域名注册虚拟主机服务
http://www.west263.com
以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢!

热点关注
IDC资讯 虚拟主机 域名注册 托管租用 vps主机 智能建站
网站运营 建站经验 策划盈利 搜索优化 网站推广 免费资源
网站联盟 联盟新闻 联盟介绍 联盟点评 网赚技巧
行业资讯 业界动态 搜索引擎 网络游戏 门户动态 电子商务 广告传媒
网络编程 Asp.Net编程 Asp编程 Php编程 Xml编程 Access Mssql Mysql 其它
服务器技术 Web服务器 Ftp服务器 Mail服务器 Dns服务器 安全防护
软件技巧 其它软件 Word Excel Powerpoint Ghost Vista QQ空间 QQ FlashGet 迅雷 Internet Explorer
网页制作 FrontPages Dreamweaver Javascript css photoshop fireworks Flash
程序设计 Java技术 C/C++ VB delphi
网络知识 网络协议 网络安全 网络管理 组网方案 Cisco技术
操作系统 Win2000 WinXP Win2003 Mac OS Linux FreeBSD
返回首页 |关于我们 | 联系我们 | 付款方式 | 创业联盟 | 价格总览 | 资讯中心 | 友情链接 | 网站地图 | 招贤纳士 | RSS