home *** CD-ROM | disk | FTP | other *** search
/ Programming Languages Suite / ProgLangD.iso / C++-7 / DISK11 / MFC / DOC / TN016.TX$ / tn016
Encoding:
Text File  |  1992-03-18  |  5.7 KB  |  160 lines

  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. =============================================================================
  160.