这几天在看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
};

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

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
}
输出结果如下:

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

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的真实作用了。

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24
