union初探

这几天在看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的真实作用了。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值