这几天在看MFC深入浅出,看到一个union的定义,代码如下:
1union MessageMapFunctions
2{
3 AFX_PMSG pfn; // generic member function pointer
4
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
56 // type safe variant for thread messages
57 void (AFX_MSG_CALL CWinThread::*pfn_THREAD)(WPARAM, LPARAM);
58
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
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
72 void (AFX_MSG_CALL CCmdTarget::*pfnCmd_v_pv)(void*);
73 BOOL (AFX_MSG_CALL CCmdTarget::*pfnCmd_b_pv)(void*);
74
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
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
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
3typedef void (*FUNC)(void);
4
5typedef void (*Func01)(int, int);
6typedef double (*Func02)(double, double);
7typedef int (*Func03)(int, int);
8
9void Test01(int, int);
10double Test02(double, double);
11int Test03(int, int);
12
13union UnionTest {
14 FUNC pFunc;
15
16 Func01 func01;
17 Func02 func02;
18 Func03 func03;
19};
20
21int _tmain(int argc, char* argv[])
22{
23 system("cls");
24 printf("此程序模仿了MFC中的消息函数分配机制\n");
25 union UnionTest test;
26
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
31 test.func01(10,10);
32 test.func02(10.001, 20.002);
33 test.func03(10,10);
34 printf("\n");
35
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
40 test.func01(10,10);
41 double xx = test.func02(10.001, 20.002);
42 test.func03(10,10);
43 printf("\n");
44
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
49 test.func01(10,10);
50 double y01 = test.func02(10.001, 20.002);
51 int yy = test.func03(10,10);
52
53 return 0;
54}
55
56void Test01(int x, int y) {
57 printf("hehe, test it. x=%d, y=%d\n", x, y);
58}
59
60double 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
66int 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))
300401000, 00401000, 00401000
4hehe, test it. x=10, y=10
5hehe, test it. x=309237645, y=1076101251
6hehe, test it. x=10, y=10
7
8(FUNC)(static_cast< double (*)(double, double) > (Test02))
900401020, 00401020, 00401020
10sum double: 0.0000000000+0.0000000000=0.0000000000
11x address:0012FEB0
12y address:0012FEB8
13sum double: 10.0010000000+20.0020000000=30.0030000000
14x address:0012FED8
15y address:0012FEE0
16sum double: 0.0000000000+10.0010000000=10.0010000000
17x address:0012FED0
18y address:0012FED8
19
20(FUNC)(static_cast< int (*)(int, int) > (Test03))
2100401070, 00401070, 00401070
22sum int: 10+10=20
23sum int: 309237645+1076101251=1385338896
24sum int: 10+10=20 从输出结果可以看出,union的每个成员的内存地址都是一样的。 这样就好理解union MessageMapFunctions的真实作用了。
阅读(1881) | 评论(0) | 转发(0) |