这几天在看MFC深入浅出,看到一个union的定义,代码如下:
1
union 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
3
typedef void (*FUNC)(void);
4
5
typedef void (*Func01)(int, int);
6
typedef double (*Func02)(double, double);
7
typedef int (*Func03)(int, int);
8
9
void Test01(int, int);
10
double Test02(double, double);
11
int Test03(int, int);
12
13
union UnionTest {
14
FUNC pFunc;
15
16
Func01 func01;
17
Func02 func02;
18
Func03 func03;
19
};
20
21
int _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
56
void Test01(int x, int y) {
57
printf("hehe, test it. x=%d, y=%d\n", x, y);
58
}
59
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
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
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
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的真实作用了。
阅读(1943) | 评论(0) | 转发(0) |