Annotation of mstools/mfc/doc/tn016.txt, revision 1.1

1.1     ! root        1: Microsoft Foundation Classes                           Microsoft Corporation
        !             2: Technical Notes
        !             3: 
        !             4: #16 : MFC and Multiple Inheritance
        !             5: 
        !             6: This note describes how to use Multiple Inheritance (MI) with
        !             7: the Microsoft Foundation Classes.
        !             8: 
        !             9: =============================================================================
        !            10: Why Multiple Inheritance ?
        !            11: ==========================
        !            12: 
        !            13: There is an ongoing debate in the C++ and object oriented communities
        !            14: over the value of multiple inheritance (MI).   The C7 compiler
        !            15: and development environment fully supports MI.
        !            16: 
        !            17: The MFC class library has been designed so that you do not need to
        !            18: understand MI to use it.  MI is not used in any of the MFC classes.
        !            19: We have found that MI is not required to write a class library,
        !            20: nor is it required for writing serious applications.
        !            21: The use of MI or not can be a personal decision, so we leave that
        !            22: decision to you.
        !            23: 
        !            24: So you want to use MI?
        !            25: ======================
        !            26: If you already understand how to use MI, understand
        !            27: the performance trade-offs, and want to use MFC,
        !            28: this technote will tell you what you must do.
        !            29: Some of the restrictions are general C++ restrictions,
        !            30: others are imposed by the MFC architecture.
        !            31: 
        !            32: There is one MFC sample that uses MI.  The MINSVRMI example
        !            33: (in \c700\mfc\samples\minsvrMI) is a minimal OLE server that
        !            34: is implemented with one class.  The non-MI version is called
        !            35: MINSVR (in \c700\mfc\samples\minsvr) and is implemented
        !            36: with 5 classes.
        !            37: 
        !            38: This is perhaps an excessive example of using MI (5 base classes),
        !            39: but it illustrates the points made here.
        !            40: 
        !            41: =============================================================================
        !            42: CObject - the root of all classes
        !            43: =================================
        !            44: 
        !            45: As you know, all significant classes derive directly or indirectly
        !            46: from CObject.  CObject does not have any member data, but does
        !            47: have some default functionality.
        !            48: 
        !            49: When using MI, it will be common to inherit from two or more
        !            50: CObject derived classes, for example a CFrameWnd and a CObList:
        !            51: 
        !            52:     class CListWnd : public CFrameWnd, public CObList
        !            53:     {
        !            54:      ...
        !            55:     };
        !            56:     CListWnd myListWnd;
        !            57: 
        !            58: In this case CObject is included twice, which leads to two problems:
        !            59:     1) any reference to CObject member functions must be disambiguated.
        !            60: 
        !            61:         myListWnd.Dump(afxDump);
        !            62:             // compile time error, CFrameWnd::Dump or CObList::Dump ?
        !            63: 
        !            64:     2) static member functions, including 'operator new' and 'operator delete'
        !            65:         must also be disambiguated.
        !            66: 
        !            67: Recommended steps:
        !            68: ------------------
        !            69: When creating a new class with two or more CObject derived base classes,
        !            70: re-implement those CObject member that you expect people to use.
        !            71: 
        !            72: Operators 'new' and 'delete' are mandatory, Dump is recommended.
        !            73: 
        !            74:     class CListWnd : public CFrameWnd, public CObList
        !            75:     {
        !            76:     public:
        !            77:         void* operator new(size_t nSize)
        !            78:             { return CFrameWnd::operator new(nSize); }
        !            79:         void operator delete(void* p)
        !            80:             { CFrameWnd::operator delete(p); }
        !            81: 
        !            82:         void Dump(CDumpContent& dc)
        !            83:             { CFrameWnd::Dump(dc);
        !            84:               CObList::Dump(dc); }
        !            85:          ...
        !            86:     };
        !            87: 
        !            88: Virtual inheritance of CObject ?
        !            89: ---------------------------------
        !            90: You may ask, "why not inherit CObject virtually, won't all of
        !            91: the ambiguity problems go away ?".
        !            92: 
        !            93: Well first of all, even in the efficient Microsoft Object Model,
        !            94: virtual inheritance is not as efficient as non-virtual inheritance
        !            95: (just as Multiple inheritance is not as efficient as single
        !            96: inheritance in certain cases.) Since there is no member data in 
        !            97: CObject, virtual inheritance is not needed to prevent multiple 
        !            98: copies of a base class's member data.
        !            99: 
        !           100: The real answer is no, virtual inheritance will not solve
        !           101: all the ambiguity problems illustrated above.
        !           102: For example: the Dump virtual member function is still
        !           103: ambiguous (since CFrameWnd and CObList implement it
        !           104: differently).
        !           105: 
        !           106: Therefore we recommend following the steps above to provide 
        !           107: disambiguation where you think it is important.
        !           108: 
        !           109: =============================================================================
        !           110: CObject - IsKindOf and runtime typing
        !           111: =====================================
        !           112: 
        !           113: The runtime typing mechanism supported by MFC in CObject uses
        !           114: the macros DECLARE_DYNAMIC, IMPLEMENT_DYNAMIC, DECLARE_SERIAL
        !           115: and IMPLEMENT_SERIAL.
        !           116: The resulting programmer feature is the ability to do a runtime
        !           117: type check to allow for safe cast-downs.
        !           118: 
        !           119: These macros only support a single base class, and will work
        !           120: in a limited way for multiply inherited classes.
        !           121: The base class you specify in IMPLEMENT_DYNAMIC or IMPLEMENT_SERIAL
        !           122: should be the first (or "left-most") base class.  For our example:
        !           123: 
        !           124:     class CListWnd : public CFrameWnd, public CObList
        !           125:     {
        !           126:         DECLARE_DYNAMIC(CListWnd)
        !           127:         ...
        !           128:     };
        !           129: 
        !           130:     IMPLEMENT_DYNAMIC(CListWnd, CFrameWnd)
        !           131: 
        !           132: This will allow you to do type checking for the "left-most" base class
        !           133: only.  The runtime type system will know nothing about additional
        !           134: bases (CObList in this case).
        !           135: 
        !           136: =============================================================================
        !           137: CWnd - and message maps
        !           138: =======================
        !           139: 
        !           140: In order for the MFC message map system to work correctly, there are
        !           141: two additional requirements:
        !           142: 
        !           143: 1) there must be only one CWnd derived base class
        !           144: 2) that CWnd derived base class must be the first (or "left-most")
        !           145:         base class.
        !           146: 
        !           147: In the example above, we have made sure that 'CFrameWnd' is the
        !           148: first base class.
        !           149: 
        !           150: Some counter examples:
        !           151:         class CTwoWindows : public CFrameWnd, public CEdit
        !           152:         { ... };
        !           153:                 // error : two copies of CWnd
        !           154: 
        !           155:         class CListEdit : public CObList, public CEdit
        !           156:         { ... };
        !           157:                 // error : CEdit (derived from CWnd) must be first
        !           158: 
        !           159: =============================================================================

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.