发信人: girlrong()
整理人: wenbobo(2002-12-06 23:08:29), 站内信件
|
按照tengel和repus的提示,我用如下方法,总算将一个类对象里的函数指针 pFun指向了另一个类对象里的非静态成员函数GetResult(不过这个成员函数用的 是_stdcall调用协议),而且还能用这个函数指针来调用GetResult了。原来要改 变调用协议,不能用类成员函数默认的thiscall调用协议。但是还有个问题。 举个例子吧,我写一个类,例如叫CCommonClass,它开了一个某种类型的窗 口,当用鼠标双击了某个区域时,该类的鼠标消息处理函数将调用该类的一个函 数指针指向的一个外部类的成员函数,将坐标值传出去。为了使CCommonClass成 为一个通用的类,CCommonClass必须不知道这个外部类的类名,也不知道这个成 员函数的名字,所以得用函数指针实现。使用CCommonClass的人只需提供一个符 合要求的函数给CCommonClass类,记录在CCommonClass类的一个函数指针成员里 ,用来接收结果就可以了。
假设在一个叫做CUserClass的类里使用CCommonClass类,非常遗憾的是在CCo mmonClass类里要引用CUserClass的类名和对象指针。而按照我的设想,为了使C CommonClass类成为通用的,事先不可能知道CUserClass的具体类型和类名,不可 能去引用CUserClass的类名和对象指针。这下完了,CCommonClass类必须知道CU serClass的类名,成不了通用的了。
虽然CCommonClass可以给CUserClass发个通知消息,告诉结果,但这又要求 CUserClass要从CWnd类派生,所以想试试别的方法。
源代码如下,恳请C++高手们指点。为了简单,把它改写成console程序了。
#include <stdio.h> #define CALLBACK _stdcall
class CUserClass;
class CCommonClass { //这就是想成为通用类的类。可是却不得不引用了CUserClass的类名 public: CCommonClass(); void SetFunc(CUserClass*pu,void (CALLBACK CUserClass::*fun)(int a) ); void OnResult(); private: void (CALLBACK CUserClass::*pFun)(int a); CUserClass* pUserObject; }; void CCommonClass::SetFunc(CUserClass* pu,void (CALLBACK CUserClass::* fun)(int a)) { //外部使用者CUserClass类对象就通过这个函数提供一个符合 //要求的用来接收结果的函数 pFun=fun; pUserObject=pu; };
CCommonClass::CCommonClass() { pFun=NULL;pUserObject=NULL; }
void CCommonClass::OnResult() { //假设CCommonClass类有了结果后就在这里调用pFun所指向的函数 (pUserObject->*pFun)(3);//假设3就是结果。 } ///////////////////////////////////////// class CUserClass { //假设这是任意一个使用CCommonClass类的类。 //按照设想,这个使用者的名字应该是任意的, //但现在如果不叫CUserClass的话就无法使用CCommonClass类。 public: CCommonClass CommonObject; void DoWork(); void CALLBACK GetResult(int a); };
void CUserClass::DoWork() { //在这里向CCommonClass对象提供一个符合要求的函数 CommonObject.SetFunc(this,GetResult); }
void CALLBACK CUserClass::GetResult(int a) { //在CUerClass里接收CCommonClass的处理结果 printf("结果是:%d\n\n",a); }
////////////////////////////////////////////////
int main() { CUserClass MyObject; MyObject.DoWork(); MyObject.CommonObject.OnResult();//模拟获得了结果 return 1; }
-- ※ 来源:.月光软件站 http://www.moon-soft.com.[FROM: 202.103.244.5] 发信人: tengel (Dragon), 信区: CLanguage 标 题: Re: 难道就不能用这种方法编写通用类 发信站: 网易虚拟社区 (Sat Nov 6 09:30:28 1999), 站内信件
【 在 girlrong (阿蓉) 的大作中提到: 】 看看MFC的CRunTimeClass怎么做的,虽然那样做很麻烦,但至少我 想已经达到了你的部分目的. 另外,RTTI能否实现你的目的呢?我想你可以试一试:typeid 和typename 两个关键字,使用模板.我现在没有时间,如果你能试出来, 可否告诉我?
-- 独进小楼成一统,管他冬夏与春秋
※ 来源:.月光软件站 http://www.moon-soft.com.[FROM: 202.104.33.10] 发信人: supermario (Mario), 信区: CLanguage 标 题: Re: 难道就不能用这种方法编写通用类 发信站: 网易虚拟社区 (Sat Nov 6 16:42:27 1999), 站内信件
【 在 girlrong (阿蓉) 的大作中提到: 】 看来阿蓉研究的问题已经很有深度了,真是三天不学习,赶不上阿蓉了, 对于C++我研究不深,说说我的想法吧,既然你这个类是用于供其他类 使用的,为什么不将它作为一个基类,由其他的类来继承呢?如果通过 这种函数指针的方式,总觉得容易破坏类的封装性。另外在定义函数时 ,好像可以通过宏定义的方式来定义参数,然后强迫类型转换,就象VC 里的Assert一样。 以前我用过这样的方式,不过是SDK形式,不知道C++中是否合法 宏定义: #define ALLOC_TABLE_HEAD(pTableHead,TableStruct) \ { \ if(!pTableHead){ \ pTableHead = (TableStruct *)malloc(sizeof(TableStruct));\ if (pTableHead == NULL)\ return FALSE;\ pTableHead->next = NULL; \ } \ } 引用宏: ALLOC_TABLE_HEAD(fav_long_date_head,fav_date)
----------------------------------------------------------- 阿蓉,当心智商太高嫁不出去了,呵呵 -----------------------------------------------------------
-- 点解啊,点解啊? -- 捶胸蹬足状
※ 修改:.supermario 于 Nov 6 16:51:47 修改本文.[FROM: 202.102.171.135] ※ 来源:.月光软件站 http://www.moon-soft.com.[FROM: 202.102.171.135] 发信人: zelor (张作乐), 信区: CLanguage 标 题: Re: 难道就不能用这种方法编写通用类 发信站: 网易虚拟社区 (Sat Nov 6 19:06:24 1999), 站内信件
哇,好过瘾,脑细胞好像进了一次健身房。只是小生我驽钝,看得我 一知半解。 P.S. 玛利,小心言多必失,万一被阿蓉点了哑穴可就…… 【 在 supermario (Mario) 的大作中提到: 】 -- 生活,就是理想加泡面。3m --------张作乐--'-<@ 送你一束玫瑰
※ 来源:.月光软件站 http://www.moon-soft.com.[FROM: 202.103.46.194] 发信人: zelor (张作乐), 信区: CLanguage 标 题: Re: 难道就不能用这种方法编写通用类 发信站: 网易虚拟社区 (Sat Nov 6 19:10:23 1999), 站内信件
使用指向函数的指针确实有点破坏封装性,不过这个方法如果成功也是 可以更大程度的实现代码重用,倒也是OOP的原意嘛。 -- 冬雷滚滚夏雨雪, 山无棱,天地合, WINDOWS再没有BUG, 才敢与君绝! ———作乐的爱情格言
※ 来源:.月光软件站 http://www.moon-soft.com.[FROM: 202.103.46.194] 发信人: girlrong (阿蓉), 信区: CLanguage 标 题: Re: 难道就不能用这种方法编写通用类 发信站: 网易 BBS (Sat Nov 6 19:44:09 1999), 转信
【 在 supermario (Mario) 的大作中提到: 】 作为基类不符合要求。比如,如果这个类是个视图类,使用它的是框架窗口类, 总不能从这个视图类派生一个框架窗口类吧?使用这个视图类的还多了,还有文档。 他们都各是各的类,不好派生的。
-- ※ 来源:.网易 BBS bbs.netease.com.[FROM: 202.103.243.27] 发信人: repus (Super), 信区: CLanguage 标 题: Re: 难道就不能用这种方法编写通用类 发信站: 网易虚拟社区 (Sat Nov 6 21:22:06 1999), 站内信件
【 在 girlrong (阿蓉) 的大作中提到: 】 你再去看看,以他最普通的调用方式,还能访问他自己类里的成员吗? -- ※ 来源:.月光软件站 http://www.moon-soft.com.[FROM: 202.101.2.141] 发信人: girlrong (阿蓉), 信区: CLanguage 标 题: Re: 难道就不能用这种方法编写通用类 发信站: 网易虚拟社区 (Sun Nov 7 09:04:55 1999), 站内信件
【 在 repus (Super) 的大作中提到: 】 你是说那个GetResult函数能不能调用同类里的别的成员函数吗?可以呀: void CALLBACK CUserClass::GetResult(int a) { //在CUerClass里接收CCommonClass的处理结果 PrintOut(a); } void CUserClass::PrintOut(int a) { printf("结果是:%d\n\n",a); }
PrintOut()就是个普通的成员函数,虽然GetResult()是CALLBACK协议,但也 可以调用它。甚至这样也可以: void CALLBACK CUserClass::GetResult(int a) { //在CUerClass里接收CCommonClass的处理结果 this->PrintOut(a); } void CUserClass::PrintOut(int a) { printf("结果是:%d\n\n",a); }
本类中别的成员函数也可以正常调用GetResult。
-- ※ 来源:.月光软件站 http://www.moon-soft.com.[FROM: 202.103.243.31] 发信人: zelor (张作乐), 信区: CLanguage 标 题: Re: 难道就不能用这种方法编写通用类 发信站: 网易虚拟社区 (Sun Nov 7 20:31:23 1999), 站内信件
阿蓉啊,你的问题让我头大了两天。迷迷糊糊的感觉忽然有个想法, 能不能用指向函数的指针的指针。(呵呵,我的感觉,想隐藏什么东西 就用指针)不过我是想不清楚了,只是瞎说一句,希望能给你提供点线索。 刚抄了你的源码回去继续想,我只求能从中学点东西啦。 P.S. CRAZYJAVA呢?怎么没看到你的意见?
-- 生活,就是理想加泡面。 --------张作乐--'-<@ 送你一束玫瑰
※ 来源:.月光软件站 http://www.moon-soft.com.[FROM: 202.103.46.194] 发信人: girlrong (阿蓉), 信区: CLanguage 标 题: Re: 难道就不能用这种方法编写通用类 发信站: 网易 BBS (Sun Nov 7 20:36:02 1999), 转信 谢谢zelor。我试试看。
-- ※ 来源:.网易 BBS bbs.netease.com.[FROM: 202.103.243.8]
|
|