要實(shí)現(xiàn)接口的話,必須使用多重繼承機(jī)制

字號(hào):

C++中,如果要實(shí)現(xiàn)接口的話,必須使用多重繼承機(jī)制。MFC中,假如我們有一個(gè)類(lèi),既需要從MFC窗口類(lèi)派生,又需要實(shí)現(xiàn)我們程序內(nèi)部的一個(gè)接口,例如下面的代碼。
    class MyBaseClass
    {
    public:
    virtual ~MyBaseClass(){}
    }
    class MyDialog : public MyBaseClass, public CDialog
    {
    ...
    }
    如果在這類(lèi)里添加消息映射函數(shù)的話,考試.大提示添加OnLButtonDown消息函數(shù)
    class MyBaseClass
    {
    public:
    virtual ~MyBaseClass(){}
    }
    class MyDialog : public MyBaseClass, public CDialog
    {
    public:
    DECLARE_MESSAGE_MAP()
    afx_msg void OnLButtonDown(UINT flag, CPoint point);
    }
    //.c文件
    BEGIN_MESSAGE_MAP(MyDialog, CDialog)
    ON_WM_LBUTTONDOWN()
    END_MESSAGE_MAP()
    void MyDialog::OnLButtonDown(UINT flag, CPoint point)
    {
    }
    當(dāng)點(diǎn)擊點(diǎn)擊MyDialog激活該消息時(shí)會(huì)出現(xiàn)異常。
    出現(xiàn)這個(gè)異常的原因很簡(jiǎn)單,但是調(diào)查過(guò)程還是比較難的。很顯然這個(gè)異常的原因是出現(xiàn)在消息映射部分。
    我們看看ON_WM_LBUTTONDOWN()這個(gè)宏的定義:
    #define ON_WM_LBUTTONDOWN() \
    { WM_LBUTTONDOWN, 0, 0, 0, AfxSig_vwp, \
    (AFX_PMSG)(AFX_PMSGW) \
    (static_cast< void (AFX_MSG_CALL CWnd::*)(UINT, CPoint) > ( &ThisClass :: OnLButtonDown)) },
    可以看到,MyDialog::OnLButtonDown的函數(shù)地址被強(qiáng)制轉(zhuǎn)化為void (AFX_MSG_CALL CWnd::*)(UINT, CPoint)函數(shù)類(lèi)型了。
    這樣一說(shuō)就能夠完全明白了,對(duì)象成員函數(shù)的指針類(lèi)型在使用時(shí)必須要2個(gè)參數(shù):變量地址和成員函數(shù)的地址。MFC函數(shù)在調(diào)用該函數(shù)的時(shí)候是這樣調(diào)用的:
    (this->*mmf.pfn_v_u_p)(static_cast(wParam), point);
    其中mmf.pfn_v_u_p就是MyDialog::OnLButtonDown的地址,而對(duì)象的地址(MyDialog對(duì)象的地址)被直接當(dāng)成CWnd的地址了。所以這里要求MFC類(lèi)必須作為第一個(gè)父類(lèi)。因?yàn)楫?dāng)成第二父類(lèi)的時(shí)候,從對(duì)象地址到CWnd地址要差一個(gè)虛函數(shù)表指針的大小,這個(gè)虛函數(shù)表是第一父類(lèi)的需函數(shù)表(當(dāng)然,第一父類(lèi)至少要包含一個(gè)virtual函數(shù),不相信這個(gè)問(wèn)題的朋友可以試試在第一父類(lèi)一個(gè)虛函數(shù)也不聲明,這個(gè)時(shí)侯就沒(méi)有這個(gè)問(wèn)題了)。這應(yīng)該是MFC實(shí)現(xiàn)時(shí)的疏忽吧,因?yàn)榭梢院?jiǎn)單的在DECLARE_MESSAGE_MAP()宏里添加一個(gè)虛函數(shù)即可:
    #define DECLARE_MESSAGE_MAP() \
    MFC_DECLARE_MESSAGE_MAP(); \
    virtual GetMFCObject(){return (CObject*)this;}
    在調(diào)用消息映射函數(shù)時(shí)改為:
    (this->GetMFCObject()->*mmf.pfn_v_u_p)(static_cast(wParam), point);
    就應(yīng)該可以了