#define DECLARE_MESSAGE_MAP() \
private: \
static const AFX_MSGMAP_ENTRY _messageEntries[]; \
protected: \
static AFX_DATA const AFX_MSGMAP messageMap; \
virtual const AFX_MSGMAP* GetMessageMap() const; \#define BEGIN_MESSAGE_MAP(theClass, baseClass) \
const AFX_MSGMAP* theClass::GetMessageMap() const \
{ return &theClass::messageMap; } \
AFX_COMDAT AFX_DATADEF const AFX_MSGMAP theClass::messageMap = \
&baseClass::messageMap&theClass::_messageEntries[0] }; \
AFX_COMDAT const AFX_MSGMAP_ENTRY theClass::_messageEntries[] = \
{ \越看问题越多,这些是MFC源码,这些明明都是私有跟保护成员,居然可以在类体访问,郁闷!还望高人指点一二。

解决方案 »

  1.   

    lz可能没看清楚,theClass::_messageEntries这个代码是写在theClass的方法内的。
      

  2.   

    #define BEGIN_MESSAGE_MAP(theClass, baseClass) 
    这是宏,在编译时会被展开替换掉的,
    例如:#define BEGIN_MESSAGE_MAP(CMyWnd, CWnd) 
    会被展开成:
    const AFX_MSGMAP* CMyWnd::GetMessageMap() const

        return &CMyWnd::messageMap; 

    AFX_COMDAT AFX_DATADEF const AFX_MSGMAP CMyWnd::messageMap = 
    { &CWnd::messageMap, &CMyWnd::_messageEntries[0] }; MFC的消息机制原理就是建立了一张静态的消息映射表,通过上面的宏展开你应该不难看出。这几个宏的定义就是对每个对象的消息映射表进行赋值,也是_messageEntries[]这个结构数组,并将对象指针加入到映射表之中,呵呵建议你看下侯捷的深入浅出MFC,里面有详细的解释
      

  3.   

    郁闷 主要是今天被另一个问题给折磨的头晕啦 
    本来是想说在类体外的 结果却说成了类体内 ,不好意思 让大家笑话啦。但是这个问题还是存在的 
    #define 宏 明显是在类体外展开的,又如何去访问 
    &baseClass::messageMap, &theClass::_messageEntries[0]
      

  4.   


    俺真的没喝酒,就是一个上午都没找到BUG,还顺带发现了这个疑惑,郁闷,侯捷那本书里边,这些成员都是public,只是为了仿真,没考虑太多,可是MFC源码就不一样啦,一般声明都是protected,可是我觉得在类体外是无法访问protected的,我肯定是漏掉了什么,只是自己美看出来,望高手详细讲一下。
      

  5.   


    谢谢回帖,请详细说一下,关于 DELACRE_MESSAGE_MAP 这个宏肯定是写在类体内啦,但是BEGIN_MESSAGE_MAP却是写在类体外的,一开始我也用红色字体表明啦,message_Map以及_messageEntries[]却是private以及protected,所以比较郁闷。我肯定是漏了什么,请指点一下。
      

  6.   

    楼主看看吧。。
    其实还是在同一个类里面的阿。。theClass是你外面传进去的那个类阿。。
    其实就在同一个类里面的。。
      

  7.   

    比如
    Class A --.h文件
    {
      DECLARE_DYNAMIC(A);  
    }
    --.CPP文件
    BEGIN_MESSAGE_MAP(A, CDialog)
    END_MESSAGE_MAP()都是类A啊,就相当于在同一类A里面阿。。
      

  8.   

    这是个成员变量,而且是静态的,展开后是对成员变量赋值,写个简单的:A.h文件
    class A
    {
    public:
    A();
    virtual ~A();
    private:
    static const int v[];
    };..........
    A.cpp文件int A::v[] = {1,2,3,......4,5,0};这就是那个宏的真正目的,你把int类型换成函数的结构体就会得到一张消息入口表。
      

  9.   

    再发一个我写过的用于对象间进行消息通讯的类给你看一下,基本就是模仿MFC的消息机制做的,用于降低模块间耦和,是个很好的模式class CXKCmd;typedef void (CXKCmd::*XK_PMSG) (void);
    typedef void (CXKCmd::*XK_PCMD) (void);
    typedef Tbool (CXKCmd::*XK_PTRANSDATA) (CXKTransData*);
    typedef Tbool (CXKCmd::*XK_PBV) (void);
    typedef Tbool (CXKCmd::*XK_PBU) (Tuint);
    typedef Tbool (CXKCmd::*XK_PBUU) (Twparam, Tlparam);
    typedef Tbool (CXKCmd::*XK_PBVPB) (void *, Tbool);
    typedef Tuint (CXKCmd::*XK_PUVPII) (void *, Tint, Tint);
    typedef Tuint (CXKCmd::*XK_PUUII) (Tuint, Tint, Tint);
    typedef void (CXKCmd::*XK_PVPIIBB) (Tint, Tint, Tbool, Tbool);
    typedef void (CXKCmd::*XK_PVPVP) ( void *, void * );
    typedef Tbool (CXKCmd::*XK_PBUVPVP)( void*, void* );
    typedef Tbool (CXKCmd::*XK_PBVP)(void *);
    typedef Tbool (CXKCmd::*XK_PBVPCP)(void *,char* );enum XKSig
    {
    XKSig_end = 0, // 消息映射结束
    XKSig_cmd,
    XKSig_transdata,
    XKSig_pbv,
    XKSig_pbu,
    XKSig_pbuu,
    XKSig_uuii,
    XKSig_bvpb,
    XKSig_uvpii,
    XKSig_vpvp,
    XKSig_buvpvp,
    XKSig_bvp,
    XKSig_vpiibb,
    XKSig_bvpcp
    };
    union XK_MSG_FUNCTION
    {
    XK_PMSG fnPMSG;
    XK_PCMD fnPCMD;
    XK_PTRANSDATA fnPTRANSDATA;
    XK_PBV fnPBV;
    XK_PBU fnPBU;
    XK_PBUU fnPBUU;
    XK_PUUII fnPUUII;
    XK_PBVPB fnPBVPB;
    XK_PUVPII fnPUVPII;
    XK_PVPVP fnPVPVP;
    XK_PBUVPVP fnPBUVPVP;
    XK_PBVP fnPBVP;
    XK_PVPIIBB fnPVPIIBB;
    XK_PBVPCP fnPBVPCP;
    };#define  XK_ON_COMMAND( msgID, memberFxn ) \
    { (Tuint)msgID, (Tuint)0, XKSig_cmd, (XK_PMSG) memberFxn },#define XK_ON_TRANSDATA( msgID, memberFxn ) \
    { (Tuint)msgID, (Tuint)0, XKSig_transdata, (XK_PTRANSDATA)memberFxn },#define  XK_ON_PBV( msgID, memberFxn ) \
    { (Tuint)msgID, (Tuint)0, XKSig_pbv, (XK_PMSG)(XK_PBV) memberFxn },#define  XK_ON_PBU( msgID, memberFxn ) \
    { (Tuint)msgID, (Tuint)0, XKSig_pbu, (XK_PMSG)(XK_PBU) memberFxn },#define  XK_ON_PBUU( msgID, memberFxn ) \
    { (Tuint)msgID, (Tuint)0, XKSig_pbuu, (XK_PMSG)(XK_PBUU) memberFxn },#define  XK_ON_UUII( msgID, memberFxn ) \
    { (Tuint)msgID, (Tuint)0, XKSig_uuii, (XK_PMSG)(XK_PUUII) memberFxn },#define XK_ON_BVPB( msgID, memberFxn )\
    { (Tuint)msgID, (Tuint)0, XKSig_bvpb, (XK_PMSG)(XK_PBVPB) memberFxn },#define XK_ON_UVPII( msgID, memberFxn )\
    { (Tuint)msgID, (Tuint)0, XKSig_uvpii, (XK_PMSG)(XK_PUVPII) memberFxn },#define XK_ON_VPVP( msgID, memberFxn )\
    { (Tuint)msgID, (Tuint)0, XKSig_vpvp, (XK_PMSG)(XK_PVPVP) memberFxn },#define XK_ON_BUVPVP( msgID, memberFxn )\
    { (Tuint)msgID, (Tuint)0, XKSig_buvpvp, (XK_PMSG)(XK_PBUVPVP) memberFxn },#define XK_ON_BVP( msgID, memberFxn )\
    { (Tuint)msgID, (Tuint)0, XKSig_bvp, (XK_PMSG)(XK_PBVP) memberFxn },#define XK_ON_VPIIBB( msgID, memberFxn )\
    { (Tuint)msgID, (Tuint)0, XKSig_vpiibb, (XK_PMSG)(XK_PVPIIBB) memberFxn },#define XK_ON_BVPCP( msgID, memberFxn )\
    { (Tuint)msgID, (Tuint)0, XKSig_bvpcp, (XK_PMSG)(XK_PBVPCP) memberFxn },struct XK_MSGMAP_ENTRY
    {
    Tuint nMessage; // 消息ID
    Tuint nID; // 对象ID
    Tuint nSig; // 消息响应函数类型
    XK_PMSG pfn; // 消息处理函数
    };struct XK_MSGMAP
    {
    XK_MSGMAP *pBaseMessageMap;
    XK_MSGMAP_ENTRY *lpEntries;
    };#define XKDEC_MESSAGE_MAP() \
    static XK_MSGMAP_ENTRY msgEntries[]; \
    static XK_MSGMAP msgMap; \
    virtual XK_MSGMAP *GetMessageMap() const;#define XKBEG_MESSAGE_MAP( theClass, baseClass ) \
    XK_MSGMAP *theClass::GetMessageMap() const \
    { return &theClass::msgMap; } \
    XK_MSGMAP theClass::msgMap = \
    { &(baseClass::msgMap), \
    ( XK_MSGMAP_ENTRY * ) &( theClass::msgEntries ) }; \
    XK_MSGMAP_ENTRY theClass::msgEntries[] = \
    { #define XKEND_MESSAGE_MAP() \
    { 0, 0, XKSig_end, (XK_PMSG) 0 } \
    };/* 消息宏定义 */
    #define XK_ON_MESSAGE(n,f) XK_ON_PBUU(n,f)#define XK_ON_NEW_DRAWFRAME(f) XK_ON_BVP(XK_WM_NEW_DRAWFRAME, f) // 新建框架
    #define XK_ON_ADD_DRAWFRAME(f) XK_ON_BVP(XK_WM_ADD_DRAWFRAME, f) // 增加框架
    #define XK_ON_DEL_DRAWFRAME(f) XK_ON_BVP(XK_WM_DEL_DRAWFRAME, f) // 删除框架#define XK_ON_DRAW(f) XK_ON_BVPB(XK_WM_PAINT, f) // 绘制图元消息
    #define XK_ON_ADDITEM(f) XK_ON_BVP(XK_WM_ADD_ITEM, f) // 增加图元消息
    #define XK_ON_DELITEM(f) XK_ON_PBU(XK_WM_DEL_ITEM, f) // 删除图元消息
    #define XK_ON_DELSELITEMS(f) XK_ON_PBV(XK_WM_DEL_SEL_ITEMS, f) // 删除所有选中的图元消息
    #define XK_NET_ADD_CLIENT(f) XK_ON_VPVP(XK_CMD_NETUNIT_ADD_CLIENT, f) // 增加网元客户端消息
    #define XK_NET_REMOVE_SOCKET(f) XK_ON_VPVP(XK_CMD_NETUNIT_REMOVE_SOCKET, f) // 网元释放本地套接字消息
    #define XK_ON_OPEN_NETNODE_WND(f) XK_ON_PBU(XK_WM_OPEN_NET_NODE, f) // 打开网元结点信息窗口
    #define XK_ON_CONTROL_SERVICE(f) XK_ON_PBUU(XK_WM_CONTROL_SERVICE, f) // 打开服务控制窗口
    #define XK_ON_DRAW_DRAGLINE(f) XK_ON_VPIIBB(XK_WM_DRAW_DRAGLINE, f) // 画拖动连线#define XK_ON_ADD_PROPERTY(f) XK_ON_BVP(XK_WM_ADD_PROPERTY, f) // 增加属性
    #define XK_ON_DEL_PROPERTY(f) XK_ON_BVP(XK_WM_DEL_PROPERTY, f) // 删除属性
    #define XK_ON_UPDATE_PROPERTY(f) XK_ON_BVP(XK_WM_UPDATE_PROPERTY, f) // 更新属性
    class CXKCmd : public CXKObject  
    {
    XKDEC_MESSAGE_MAP()
    public:
    CXKCmd();
    virtual ~CXKCmd();
    public:
    /* 发送命令消息 */
    virtual Tuint SendMsg(Tuint nMsgID, Tlparam lParam = 0, Twparam wParam = 0);
    /* 默认命令消息处理函数 */
    virtual Tuint DefMsgProc(Tuint nMsgID, Tlparam lParam, Twparam wParam);
    protected:
    XK_MSGMAP_ENTRY *SearchMsgEntry( Tuint nID );
    };
    这下应该明白了吧。
      

  10.   

    #include<iostream>
    using namespace std;
    class base
    {
    private:
    static int i;
    static int *p;
    };
    int base::i=10;
    int *base::p=&base::i;
    class super:public base
    {
    private:
    static int *q;
    };int *super::q=&base::i;差不多我已经明白这个问题啦,这段代码在VC6里边可以,到了VC2008就不行啦,说不能访问base的私有成员,VC6果然对标准支持的不好,不过俺多说一句,这个标准太变态啦。谢谢大家的参与,分不多。
      

  11.   


    呵呵 问题已经大致明白啦,至于消息映射机制 ,相信侯捷那本书已经说的相当明白啦,我也有看过MFC源码,这个还是很明白的,疑惑的是类定义外部怎么能访问私有成员,经过刚才的试验已经发现只有对静态变量初始化的时候才可以,如果掺和上派生类的话,那就更麻烦啦,总之C++访问控制机制太变态啦。