|
Posted on 2007-08-06 17:31 jacky_zz 阅读(1188) 评论(4) 编辑 收藏 引用 所属分类: C/C++
这几天在看MFC深入浅出,看到一个union的定义,代码如下:
1 union MessageMapFunctions 2 { 3 AFX_PMSG pfn; // generic member function pointer 4![](http://www.cppblog.com/Images/OutliningIndicators/None.gif) 5 BOOL (AFX_MSG_CALL CCmdTarget::*pfn_b_D)(CDC*); 6 BOOL (AFX_MSG_CALL CCmdTarget::*pfn_b_b)(BOOL); 7 BOOL (AFX_MSG_CALL CCmdTarget::*pfn_b_u)(UINT); 8 BOOL (AFX_MSG_CALL CCmdTarget::*pfn_b_h)(HANDLE); 9 BOOL (AFX_MSG_CALL CCmdTarget::*pfn_b_W_u_u)(CWnd*, UINT, UINT); 10 BOOL (AFX_MSG_CALL CCmdTarget::*pfn_b_W_COPYDATASTRUCT)(CWnd*, COPYDATASTRUCT*); 11 BOOL (AFX_MSG_CALL CCmdTarget::*pfn_b_HELPINFO)(LPHELPINFO); 12 HBRUSH (AFX_MSG_CALL CCmdTarget::*pfn_B_D_W_u)(CDC*, CWnd*, UINT); 13 HBRUSH (AFX_MSG_CALL CCmdTarget::*pfn_B_D_u)(CDC*, UINT); 14 int (AFX_MSG_CALL CCmdTarget::*pfn_i_u_W_u)(UINT, CWnd*, UINT); 15 int (AFX_MSG_CALL CCmdTarget::*pfn_i_u_u)(UINT, UINT); 16 int (AFX_MSG_CALL CCmdTarget::*pfn_i_W_u_u)(CWnd*, UINT, UINT); 17 int (AFX_MSG_CALL CWnd::*pfn_i_s)(LPTSTR); 18 LRESULT (AFX_MSG_CALL CWnd::*pfn_l_w_l)(WPARAM, LPARAM); 19 LRESULT (AFX_MSG_CALL CWnd::*pfn_l_u_u_M)(UINT, UINT, CMenu*); 20 void (AFX_MSG_CALL CWnd::*pfn_v_v)(); 21 int (AFX_MSG_CALL CWnd::*pfn_i_u)(UINT); 22 HCURSOR (AFX_MSG_CALL CWnd::*pfn_C_v)(); 23 UINT (AFX_MSG_CALL CWnd::*pfn_u_u)(UINT); 24 BOOL (AFX_MSG_CALL CWnd::*pfn_b_v)(); 25 void (AFX_MSG_CALL CWnd::*pfn_v_u)(UINT); 26 void (AFX_MSG_CALL CWnd::*pfn_v_u_u)(UINT, UINT); 27 void (AFX_MSG_CALL CWnd::*pfn_v_i_i)(int, int); 28 void (AFX_MSG_CALL CWnd::*pfn_v_u_u_u)(UINT, UINT, UINT); 29 void (AFX_MSG_CALL CWnd::*pfn_v_u_i_i)(UINT, int, int); 30 void (AFX_MSG_CALL CWnd::*pfn_v_w_l)(WPARAM, LPARAM); 31 void (AFX_MSG_CALL CWnd::*pfn_v_b_W_W)(BOOL, CWnd*, CWnd*); 32 void (AFX_MSG_CALL CWnd::*pfn_v_D)(CDC*); 33 void (AFX_MSG_CALL CWnd::*pfn_v_M)(CMenu*); 34 void (AFX_MSG_CALL CWnd::*pfn_v_M_u_b)(CMenu*, UINT, BOOL); 35 void (AFX_MSG_CALL CWnd::*pfn_v_W)(CWnd*); 36 void (AFX_MSG_CALL CWnd::*pfn_v_W_u_u)(CWnd*, UINT, UINT); 37 void (AFX_MSG_CALL CWnd::*pfn_v_W_p)(CWnd*, CPoint); 38 void (AFX_MSG_CALL CWnd::*pfn_v_W_h)(CWnd*, HANDLE); 39 void (AFX_MSG_CALL CWnd::*pfn_v_u_W)(UINT, CWnd*); 40 void (AFX_MSG_CALL CWnd::*pfn_v_u_W_b)(UINT, CWnd*, BOOL); 41 void (AFX_MSG_CALL CWnd::*pfn_v_u_u_W)(UINT, UINT, CWnd*); 42 void (AFX_MSG_CALL CWnd::*pfn_v_s)(LPTSTR); 43 void (AFX_MSG_CALL CWnd::*pfn_v_u_cs)(UINT, LPCTSTR); 44 void (AFX_MSG_CALL CWnd::*pfn_v_i_s)(int, LPTSTR); 45 int (AFX_MSG_CALL CWnd::*pfn_i_i_s)(int, LPTSTR); 46 UINT (AFX_MSG_CALL CWnd::*pfn_u_p)(CPoint); 47 UINT (AFX_MSG_CALL CWnd::*pfn_u_v)(); 48 void (AFX_MSG_CALL CWnd::*pfn_v_b_NCCALCSIZEPARAMS)(BOOL, NCCALCSIZE_PARAMS*); 49 void (AFX_MSG_CALL CWnd::*pfn_v_v_WINDOWPOS)(WINDOWPOS*); 50 void (AFX_MSG_CALL CWnd::*pfn_v_u_u_M)(UINT, UINT, HMENU); 51 void (AFX_MSG_CALL CWnd::*pfn_v_u_p)(UINT, CPoint); 52 void (AFX_MSG_CALL CWnd::*pfn_v_u_pr)(UINT, LPRECT); 53 BOOL (AFX_MSG_CALL CWnd::*pfn_b_u_s_p)(UINT, short, CPoint); 54 LRESULT (AFX_MSG_CALL CWnd::*pfn_l_v)(); 55![](http://www.cppblog.com/Images/OutliningIndicators/None.gif) 56 // type safe variant for thread messages 57 void (AFX_MSG_CALL CWinThread::*pfn_THREAD)(WPARAM, LPARAM); 58![](http://www.cppblog.com/Images/OutliningIndicators/None.gif) 59 // specific type safe variants for WM_COMMAND and WM_NOTIFY messages 60 void (AFX_MSG_CALL CCmdTarget::*pfnCmd_v_v)(); 61 BOOL (AFX_MSG_CALL CCmdTarget::*pfnCmd_b_v)(); 62 void (AFX_MSG_CALL CCmdTarget::*pfnCmd_v_u)(UINT); 63 BOOL (AFX_MSG_CALL CCmdTarget::*pfnCmd_b_u)(UINT); 64![](http://www.cppblog.com/Images/OutliningIndicators/None.gif) 65 void (AFX_MSG_CALL CCmdTarget::*pfnNotify_v_NMHDR_pl)(NMHDR*, LRESULT*); 66 BOOL (AFX_MSG_CALL CCmdTarget::*pfnNotify_b_NMHDR_pl)(NMHDR*, LRESULT*); 67 void (AFX_MSG_CALL CCmdTarget::*pfnNotify_v_u_NMHDR_pl)(UINT, NMHDR*, LRESULT*); 68 BOOL (AFX_MSG_CALL CCmdTarget::*pfnNotify_b_u_NMHDR_pl)(UINT, NMHDR*, LRESULT*); 69 void (AFX_MSG_CALL CCmdTarget::*pfnCmdUI_v_C)(CCmdUI*); 70 void (AFX_MSG_CALL CCmdTarget::*pfnCmdUI_v_C_u)(CCmdUI*, UINT); 71![](http://www.cppblog.com/Images/OutliningIndicators/None.gif) 72 void (AFX_MSG_CALL CCmdTarget::*pfnCmd_v_pv)(void*); 73 BOOL (AFX_MSG_CALL CCmdTarget::*pfnCmd_b_pv)(void*); 74![](http://www.cppblog.com/Images/OutliningIndicators/None.gif) 75 //OLD 76 // specific type safe variants for WM-style messages 77 // BOOL (AFX_MSG_CALL CWnd::*pfn_bD)(CDC*); 78 // BOOL (AFX_MSG_CALL CWnd::*pfn_bb)(BOOL); 79 // BOOL (AFX_MSG_CALL CWnd::*pfn_bWww)(CWnd*, UINT, UINT); 80 // BOOL (AFX_MSG_CALL CWnd::*pfn_bHELPINFO)(HELPINFO*); 81 // BOOL (AFX_MSG_CALL CWnd::*pfn_bWCDS)(CWnd*, COPYDATASTRUCT*); 82 // HBRUSH (AFX_MSG_CALL CWnd::*pfn_hDWw)(CDC*, CWnd*, UINT); 83 // HBRUSH (AFX_MSG_CALL CWnd::*pfn_hDw)(CDC*, UINT); 84 // int (AFX_MSG_CALL CWnd::*pfn_iwWw)(UINT, CWnd*, UINT); 85 // int (AFX_MSG_CALL CWnd::*pfn_iww)(UINT, UINT); 86 // int (AFX_MSG_CALL CWnd::*pfn_iWww)(CWnd*, UINT, UINT); 87 // int (AFX_MSG_CALL CWnd::*pfn_is)(LPTSTR); 88 // LRESULT (AFX_MSG_CALL CWnd::*pfn_lwl)(WPARAM, LPARAM); 89 // LRESULT (AFX_MSG_CALL CWnd::*pfn_lwwM)(UINT, UINT, CMenu*); 90 // void (AFX_MSG_CALL CWnd::*pfn_vv)(void); 91![](http://www.cppblog.com/Images/OutliningIndicators/None.gif) 92 // void (AFX_MSG_CALL CWnd::*pfn_vw)(UINT); 93 // void (AFX_MSG_CALL CWnd::*pfn_vww)(UINT, UINT); 94 // void (AFX_MSG_CALL CWnd::*pfn_vvii)(int, int); 95 // void (AFX_MSG_CALL CWnd::*pfn_vwww)(UINT, UINT, UINT); 96 // void (AFX_MSG_CALL CWnd::*pfn_vwii)(UINT, int, int); 97 // void (AFX_MSG_CALL CWnd::*pfn_vwl)(WPARAM, LPARAM); 98 // void (AFX_MSG_CALL CWnd::*pfn_vbWW)(BOOL, CWnd*, CWnd*); 99 // void (AFX_MSG_CALL CWnd::*pfn_vD)(CDC*); 100 // void (AFX_MSG_CALL CWnd::*pfn_vM)(CMenu*); 101 // void (AFX_MSG_CALL CWnd::*pfn_vMwb)(CMenu*, UINT, BOOL); 102![](http://www.cppblog.com/Images/OutliningIndicators/None.gif) 103 // void (AFX_MSG_CALL CWnd::*pfn_vW)(CWnd*); 104 // void (AFX_MSG_CALL CWnd::*pfn_vWww)(CWnd*, UINT, UINT); 105 // void (AFX_MSG_CALL CWnd::*pfn_vWp)(CWnd*, CPoint); 106 // void (AFX_MSG_CALL CWnd::*pfn_vWh)(CWnd*, HANDLE); 107 // void (AFX_MSG_CALL CWnd::*pfn_vwW)(UINT, CWnd*); 108 // void (AFX_MSG_CALL CWnd::*pfn_vwWb)(UINT, CWnd*, BOOL); 109 // void (AFX_MSG_CALL CWnd::*pfn_vwwW)(UINT, UINT, CWnd*); 110 // void (AFX_MSG_CALL CWnd::*pfn_vwwx)(UINT, UINT); 111 // void (AFX_MSG_CALL CWnd::*pfn_vs)(LPTSTR); 112 // void (AFX_MSG_CALL CWnd::*pfn_vOWNER)(int, LPTSTR); // force return TRUE 113 // int (AFX_MSG_CALL CWnd::*pfn_iis)(int, LPTSTR); 114 // UINT (AFX_MSG_CALL CWnd::*pfn_wp)(CPoint); 115 // UINT (AFX_MSG_CALL CWnd::*pfn_wv)(void); 116 void (AFX_MSG_CALL CWnd::*pfn_vPOS)(WINDOWPOS*); 117 void (AFX_MSG_CALL CWnd::*pfn_vCALC)(BOOL, NCCALCSIZE_PARAMS*); 118 void (AFX_MSG_CALL CWnd::*pfn_vwp)(UINT, CPoint); 119 void (AFX_MSG_CALL CWnd::*pfn_vwwh)(UINT, UINT, HANDLE); 120 BOOL (AFX_MSG_CALL CWnd::*pfn_bwsp)(UINT, short, CPoint); 121 // void (AFX_MSG_CALL CWnd::*pfn_vws)(UINT, LPCTSTR); 122 };
而调用的方法只是指定了一个函数指针,而函数指针的定义为: typedef void (AFX_MSG_CALL CCmdTarget::*AFX_PMSG)(void); 起初一点也不明白这样的定义怎么指向实际执行的函数?怀着这样的疑问,我自己做了个测试,才明白其中的真实含义。union与struct的区别是:union为每个成员共享一个地址空间,而struct为每个成员都分配一个地址空间。这样就好理解了,不管union里定义了多少个成员,每个成员都使用同一个内存地址,而struct的每个成员的内存地址却都不相同。 测试代码如下:
1 #include "stdafx.h" 2![](http://www.cppblog.com/Images/OutliningIndicators/None.gif) 3 typedef void (*FUNC)(void); 4![](http://www.cppblog.com/Images/OutliningIndicators/None.gif) 5 typedef void (*Func01)(int, int); 6 typedef double (*Func02)(double, double); 7 typedef int (*Func03)(int, int); 8![](http://www.cppblog.com/Images/OutliningIndicators/None.gif) 9 void Test01(int, int); 10 double Test02(double, double); 11 int Test03(int, int); 12![](http://www.cppblog.com/Images/OutliningIndicators/None.gif) 13 union UnionTest { 14 FUNC pFunc; 15![](http://www.cppblog.com/Images/OutliningIndicators/None.gif) 16 Func01 func01; 17 Func02 func02; 18 Func03 func03; 19 }; 20![](http://www.cppblog.com/Images/OutliningIndicators/None.gif) 21 int _tmain(int argc, char* argv[]) 22 { 23 system("cls"); 24 printf("此程序模仿了MFC中的消息函数分配机制\n"); 25 union UnionTest test; 26![](http://www.cppblog.com/Images/OutliningIndicators/None.gif) 27 printf("(FUNC)(static_cast< void (*)(int, int) > (Test01))\n"); 28 test.pFunc = (FUNC)(static_cast< void (*)(int, int) > (Test01)); 29 printf("%p, %p, %p\n", test.func01, test.func02, test.func03); 30![](http://www.cppblog.com/Images/OutliningIndicators/None.gif) 31 test.func01(10,10); 32 test.func02(10.001, 20.002); 33 test.func03(10,10); 34 printf("\n"); 35![](http://www.cppblog.com/Images/OutliningIndicators/None.gif) 36 printf("(FUNC)(static_cast< double (*)(double, double) > (Test02))\n"); 37 test.pFunc = (FUNC)(static_cast< double (*)(double, double) > (Test02)); 38 printf("%p, %p, %p\n", test.func01, test.func02, test.func03); 39![](http://www.cppblog.com/Images/OutliningIndicators/None.gif) 40 test.func01(10,10); 41 double xx = test.func02(10.001, 20.002); 42 test.func03(10,10); 43 printf("\n"); 44![](http://www.cppblog.com/Images/OutliningIndicators/None.gif) 45 printf("(FUNC)(static_cast< int (*)(int, int) > (Test03))\n"); 46 test.pFunc = (FUNC)(static_cast< int (*)(int, int) > (Test03)); 47 printf("%p, %p, %p\n", test.func01, test.func02, test.func03); 48![](http://www.cppblog.com/Images/OutliningIndicators/None.gif) 49 test.func01(10,10); 50 double y01 = test.func02(10.001, 20.002); 51 int yy = test.func03(10,10); 52![](http://www.cppblog.com/Images/OutliningIndicators/None.gif) 53 return 0; 54 } 55![](http://www.cppblog.com/Images/OutliningIndicators/None.gif) 56 void Test01(int x, int y) { 57 printf("hehe, test it. x=%d, y=%d\n", x, y); 58 } 59![](http://www.cppblog.com/Images/OutliningIndicators/None.gif) 60 double Test02(double x, double y) { 61 double sum =x+y; 62 printf("sum double: %10.10f+%10.10f=%10.10f\nx address:%p\ny address:%p\n",x,y,sum, &x, &y); 63 return sum; 64 } 65![](http://www.cppblog.com/Images/OutliningIndicators/None.gif) 66 int Test03(int x, int y) { 67 int sum =x+y; 68 printf("sum int: %d+%d=%d\n",x,y,sum); 69 return sum; 70 }
输出结果如下:
1 此程序模仿了MFC中的消息函数分配机制 2 (FUNC)(static_cast< void (*)(int, int) > (Test01)) 3 00401000, 00401000, 00401000 4 hehe, test it. x=10, y=10 5 hehe, test it. x=309237645, y=1076101251 6 hehe, test it. x=10, y=10 7![](http://www.cppblog.com/Images/OutliningIndicators/None.gif) 8 (FUNC)(static_cast< double (*)(double, double) > (Test02)) 9 00401020, 00401020, 00401020 10 sum double: 0.0000000000+0.0000000000=0.0000000000 11 x address:0012FEB0 12 y address:0012FEB8 13 sum double: 10.0010000000+20.0020000000=30.0030000000 14 x address:0012FED8 15 y address:0012FEE0 16 sum double: 0.0000000000+10.0010000000=10.0010000000 17 x address:0012FED0 18 y address:0012FED8 19![](http://www.cppblog.com/Images/OutliningIndicators/None.gif) 20 (FUNC)(static_cast< int (*)(int, int) > (Test03)) 21 00401070, 00401070, 00401070 22 sum int: 10+10=20 23 sum int: 309237645+1076101251=1385338896 24 sum int: 10+10=20
从输出结果可以看出,union的每个成员的内存地址都是一样的。 这样就好理解union MessageMapFunctions的真实作用了。
Feedback
不错,虽然候Sir在深入浅出中说了,但当时还是没有看明白
The <a href=" http://goodfinance-blog.com">loans</a> are useful for people, which would like to ground their own business. As a fact, this is comfortable to get a short term loan.
Look over EssaysLeader rewiew (best-essay-sites.com), select top-notch firm and purchase professionally written essays from competent writers.
|