Annotation of mstools/mfc/doc/tn016.txt, revision 1.1.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.