|
|
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: =============================================================================
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.