Aracılığıyla paylaş


TN016: C++ birden çok devralma mfc ile kullanma

Bu not, birden çok devralma (MI) ile Microsoft Foundation Sınıf kullanmayı açıklamaktadır.mfc ile MI kullanılması gerekmez.MI, herhangi bir mfc sınıflarda kullanılmaz ve sınıf kitaplığı yazmak için gerekli değildir.

Aşağıdaki alt konuları MI ortak mfc deyimleri gibi bazı MI kısıtlamaları kapsayan kullanımını nasıl etkilediği açıklanmaktadır.Bu kısıtlamalar genel C++ kısıtlamaları şunlardır.Başkalarının mfc mimarisi tarafından kullanılan.

Bu teknik bir notun sonuna mı kullanır tam bir mfc uygulaması bulacaksınız.

CRuntimeClass

Kalıcılık ve dinamik nesne oluşturma mekanizmaları mfc kullanım CRuntimeClass sınıfları benzersiz olarak tanımlamak için veri yapısı.mfc biri bu yapýlar, uygulamanızdaki her sınıf dinamik ve/veya seri hale getirilebilir ilişkilendirir.Özel bir statik nesne türü kullanarak uygulama başladığında bu yapılar başlatılan AFX_CLASSINIT.

Geçerli uygulaması CRuntimeClass MI çalışma zamanı tür bilgileri desteklemez.Bu mfc uygulamanızda MI kullanamazsınız anlamına gelmez.Ancak, birden fazla temel sınıf nesneleriyle çalışırken belirli sorumlulukları olacaktır.

CObject::IsKindOf Yöntemi değil doğru belirler bir nesne türü birden çok temel sınıflar varsa.Bu nedenle kullanamazsınız CObject sanal bir temel sınıf ve tüm aramalar için CObject üye işlevleri gibi CObject::Serialize ve Yeni CObject::operator , C++ uygun işlev çağrısı disambiguate böylece kapsam niteleyicileri olmalı.Bir program içinde mfc MI kullandığında, sınıf içeren CObject temel sınıf temel sınıflar listesinde en soldaki sınıfı olması gerekiyor.

Alternatif kullanmaktır dynamic_cast işleci.Çevrim MI temel sınıflardan birine sahip bir nesne derleyici sağlanan base sınıfında işlevleri kullanmak için zorlar.Daha fazla bilgi için bkz. dynamic_cast operatörü.

CObject - bütün sınıfların kökünün

Tüm önemli sınıflarını doğrudan veya dolaylı olarak sınıfından türeyen CObject.CObjectmu herhangi bir üye veri yoktur, ancak bazı varsayılan işlevselliği vardır.MI kullandığınızda, genellikle iki veya daha çok gruptan devralır CObject-türetilmiş sınıfları.Bir sınıf tarafından nasıl devralabilir aşağıdaki örnekte gösterilmektedir bir CFrameWnd ve CObList:

class CListWnd : public CFrameWnd, public CObList
{
 ...
};
CListWnd myListWnd;

Bu durumda CObject iki kez bulunmaktadır.Herhangi bir başvuru disambiguate için bir yol gerekir yani CObject yöntemler ya da operators.operator new Ve işletmeni silmek disambiguated gereken iki işleçlerdir.Başka bir örnek olarak, aşağıdaki kod derleme zamanında bir hata neden olur:

myListWnd.Dump(afxDump);
    // compile time error, CFrameWnd::Dump or CObList::Dump ?

Reimplementing CObject yöntemleri

Yeni bir sınıf oluşturduğunuzda, iki veya daha fazla olan CObject türetilmiş temel sınıfları reimplement CObject diğer kişilerin kullanmasını istediğiniz yöntem.İşleçleri new ve delete zorunludur ve Döküm önerilir.Aşağıdaki örnek reimplements new ve delete işleçleri ve Dump yöntemi:

class CListWnd : public CFrameWnd, public CObList
{
public:
    void* operator new(size_t nSize)
        { return CFrameWnd::operator new(nSize); }
    void operator delete(void* p)
        { CFrameWnd::operator delete(p); }

    void Dump(CDumpContent& dc)
        { CFrameWnd::Dump(dc);
          CObList::Dump(dc); }
     ...
};

CObject sanal kalıtımı

Bu neredeyse devralmasını görünebilir CObject işlevi belirsizlik sorunu çözmek, ama durum böyle değildir.Üye veri yok çünkü CObject, bir temel sınıf üyesi verileri birden çok kopyasını önlemek için sanal devralma gerekmez.Daha önce gösterilen ilk örnekteki Dump sanal bir yöntem uygulanan farklı, çünkü hala belirsiz CFrameWnd ve CObList.Belirsizlik kaldırmak için en iyi önceki bölümde sunulan önerilerini yoldur.

CObject::IsKindOf ve yazarak çalıştırma

The run-time typing mechanism supported by MFC in CObject uses the macros DECLARE_DYNAMIC, IMPLEMENT_DYNAMIC, DECLARE_DYNCREATE, IMPLEMENT_DYNCREATE, DECLARE_SERIAL and IMPLEMENT_SERIAL.Bu makrolar, güvenli downcasts güvence altına almak için bir çalışma zamanı tür kontrolü yapabilirsiniz.

Bu makrolar, yalnızca tek bir temel sınıf desteği ve çarpın devralınan sınıfları için sınırlı bir şekilde çalışır.Sizin belirlediğiniz bir temel sınıf IMPLEMENT_DYNAMIC veya IMPLEMENT_SERIAL ilk (veya en soldaki) temel sınıf olmalıdır.Bu yerleşim en soldaki için temel sınıf yalnızca denetleme yazın sağlayacaktır.Çalışma zamanı tür sistemi ek temel sınıflar hakkında bir şey biliyor.Aşağıdaki örnekte, çalışma zamanı sistemleri yapacağını yazın karşı denetleme CFrameWnd, ama hiçbir şey hakkında bilirsiniz CObList.

class CListWnd : public CFrameWnd, public CObList
{
    DECLARE_DYNAMIC(CListWnd)
    ...
};
IMPLEMENT_DYNAMIC(CListWnd, CFrameWnd)

CWnd ve ileti eşlemeleri

Düzgün çalışması mfc ileti eşleme sistemi için iki ek gereksinimleri vardır:

  • Bulunması için yalnızca bir CWnd-temel sınıf türetilir.

  • CWnd-İlk (veya en soldaki) temel sınıf türetilmiş bir temel sınıf olmalıdır.

İşe yaramaz bazı örnekler şunlardır:

class CTwoWindows : public CFrameWnd, public CEdit
    { ... };
        // error : two copies of CWnd

class CListEdit : public CObList, public CEdit
    { ... };
        // error : CEdit (derived from CWnd) must be first

Örnek MI kullanarak bir Program

Aşağıdaki örnek, türetilen bir sınıfı oluşan bağımsız bir uygulamadır CFrameWnd ve CWinApp.Bu şekilde bir uygulama yapısı, ancak bir örnek bir sınıf olan küçük mfc uygulaması önerilmez.

#include <afxwin.h>

class CHelloAppAndFrame : public CFrameWnd, public CWinApp
{ 
public:
    CHelloAppAndFrame()
        { }

    // Necessary because of MI disambiguity
    void* operator new(size_t nSize)
        { return CFrameWnd::operator new(nSize); }
    void operator delete(void* p)
        { CFrameWnd::operator delete(p); }

    // Implementation
    // CWinApp overrides
    virtual BOOL InitInstance();
    // CFrameWnd overrides
    virtual void PostNcDestroy();
    afx_msg void OnPaint();

    DECLARE_MESSAGE_MAP()

};

BEGIN_MESSAGE_MAP(CHelloAppAndFrame, CFrameWnd)
    ON_WM_PAINT()
END_MESSAGE_MAP()

// because the frame window is not allocated on the heap, we must
// override PostNCDestroy not to delete the frame object
void CHelloAppAndFrame::PostNcDestroy()
{
    // do nothing (do not call base class)
}

void CHelloAppAndFrame::OnPaint()
{
    CPaintDC dc(this);
    CRect rect;
    GetClientRect(rect);

    CString s = "Hello, Windows!";
    dc.SetTextAlign(TA_BASELINE | TA_CENTER);
    dc.SetTextColor(::GetSysColor(COLOR_WINDOWTEXT));
    dc.SetBkMode(TRANSPARENT);
    dc.TextOut(rect.right / 2, rect.bottom / 2, s);
}

// Application initialization
BOOL CHelloAppAndFrame::InitInstance()
{
    // first create the main frame
    if (!CFrameWnd::Create(NULL, "Multiple Inheritance Sample",
        WS_OVERLAPPEDWINDOW, rectDefault))
        return FALSE;

    // the application object is also a frame window
    m_pMainWnd = this;          
    ShowWindow(m_nCmdShow);
    return TRUE;
}

CHelloAppAndFrame theHelloAppAndFrame;

Ayrıca bkz.

Diğer Kaynaklar

Teknik notlar numarasına göre

Kategoriye göre teknik notlar