mult. inheritance ambiguity on MFC generated delete
Todd Davis -- tigger@idir.net Thursday, November 21, 1996 Environment: VC++ 4.1, Win 95 I'm trying to create a class which can be "mixed in" with a control to support special resizing functions within a CFormView. Here is an example of how the class is used: CWnd / \ CListCtrl CResizableCtrl \ / CMyListCtrl I have a CFormView derived class, CTestForm, with a couple of subclassed list conrols and a couple of subclassed buttons that add in this new CResizableCtrl class. class CTestForm : public CFormView { ... private: CMyListCtrl m_cList1, m_cList2; CMyButton m_cButton1, m_cButton2; } My problem lies with the MFC supplied constructor for CTestForm. IMPLEMENT_DYNCREATE(CTestForm, CFormView) CTestForm::CTestForm() : CFormView(CTestForm::IDD) { //{{AFX_DATA_INIT(CTestForm) //}}AFX_DATA_INIT } <- I get an error for both CMyListCtrl and CMyButton at the line pointed to by the "<-" stating that CMyListCtrl::delete (or CMyButton::delete) is ambiguous between the CObject ultimate base class for CListCtrl and the CObject ultimate base class for CResizableCtrl. Where is this call to delete coming from? These controls aren't dynamically created, so why call delete for them? C++ isn't supposed to complain about ambiguity unless the function being CALLED is ambiguous. I could make put my CResizableCtrl functions in the control specific derived classes and take out the mulitple inheritance, but this seemed like such a slick solution. Any ideas? Am I crazy for trying to use multiple inheritance in the first place with MFC library classes? "Thank You"s to be sent upon a solution, Todd Davis Software Engineer Gateway 2000
Eugenio Miro -- emiro@datamarkets.com.ar Saturday, November 23, 1996 [Mini-digest: 5 responses] Hi I think you are not CALLING delete, you are DECLARING two deletes in = your base classes, if you declare two virtual delete functions, compiler = don't know who to call when automatically destroys your object, that is = derived from those classes. you must declare your delete function to = break de discussion. For more info this problem is expained in Bjarne = Stroustroup's book The C++ Programming Language.=20 I hope this helps. ---------- From: Todd Davis Sent: Thursday, November 21, 1996 1:11 PM To: mfc-l@netcom.com Subject: mult. inheritance ambiguity on MFC generated delete Environment: VC++ 4.1, Win 95 I'm trying to create a class which can be "mixed in" with a control to support special resizing functions within a CFormView. Here is an = example of how the class is used: CWnd / \ CListCtrl CResizableCtrl \ / CMyListCtrl I have a CFormView derived class, CTestForm, with a couple of subclassed list conrols and a couple of subclassed buttons that add in this new CResizableCtrl class. class CTestForm : public CFormView { .. private: CMyListCtrl m_cList1, m_cList2; CMyButton m_cButton1, m_cButton2; } My problem lies with the MFC supplied constructor for CTestForm. IMPLEMENT_DYNCREATE(CTestForm, CFormView) CTestForm::CTestForm() : CFormView(CTestForm::IDD) { //{{AFX_DATA_INIT(CTestForm) //}}AFX_DATA_INIT } <- I get an error for both CMyListCtrl and CMyButton at the line pointed to = by the "<-" stating that CMyListCtrl::delete (or CMyButton::delete) is ambiguous between the CObject ultimate base class for CListCtrl and the CObject ultimate base class for CResizableCtrl. Where is this call to delete coming from? These controls aren't dynamically created, so why = call delete for them? C++ isn't supposed to complain about ambiguity unless = the function being CALLED is ambiguous. I could make put my CResizableCtrl functions in the control specific = derived classes and take out the mulitple inheritance, but this seemed like such = a slick solution. Any ideas? Am I crazy for trying to use multiple inheritance in the first place with MFC library classes? "Thank You"s to be sent upon a solution, Todd Davis Software Engineer Gateway 2000 -----From: Richard BraleyRefer to Technical Note 16: Using C++ Multiple Inheritance(MI) with the = Microsoft Foundation Classes in the MFC 3.1 Technical Notes found on the = MSDN CD. The information should still be applicable for the current MFC = Class Library. Your graphic shows you are deriving your "mixin" class = from CWnd which is ultimately derived from CObject. Therefore, the info = in this tech note should apply to you! Or, you can try and not derive = your mixin class from CWnd? Since I do not know exactly what you are = doing in this class you will have to make this determination. -----From: "Michael S. Scherotter" You cannot have a diamond shaped inheritance in C++ -- _________________________________________________________________ Michael S. Scherotter | (415) 824-9647 Software Developer | 125 Fair Oaks Street The Charette Project | San Francisco, CA 94110 Architectural Design Tools |__________________________ www.charette.com mscherotter@mailmasher.com _____________________ mss@tartus.com Michael@charette.com | 71035.1675@compuserve.com "Work as if you may live forever, live as if you might die tomorrow." -----From: Mike Kurtinitis >From what you've described it sounds like your mix-in class is derived from CObject. Since CListCtrl is also derived from CObject there *is* an ambiguity with certain member functions (namely new, delete and Dump). CObject is not a virtual base class, nor can it be made one, but there are ways to resolve the ambiguities (see TN16). Good luck, Mike Kurtinitis Mooshwerks moosh@halcyon.com -----From: cugr1@gd.swissptt.ch (Cunningham Graham, IT347) If you take a look at the technical note TN016 It describes the steps = that you need to take to implement c++ multiple inheritence with mfc, in = particular with multple CObject derived base classes.
Mike Blaszczak -- mikeblas@nwlink.com Sunday, November 24, 1996 At 09:46 11/23/96 -0000, you wrote: -----From: "Michael S. Scherotter">You cannot have a diamond shaped inheritance in C++ Yes, you can. Your asseriton is wrong. Please see (for starters) section 6.5.1 of "The C++ Programming Language" (2ed) by Bjarne Stroustrup. There, Stroustrup says: "With the ability of specifying more than one base class comes the possibility of having a class as a base class twice. For example, had _task_ and _displayed_ each been derived from a link class, a satellite [which multiply inherits from _task_ and _displayed_] would have two _link_s. [...] This causes no problems." Of course, Stroustrup is as idealistic as ever in saying that "This causes no problems", because it confuses everyone and results in some ugly and pesky ambiguity problems. But he means only that this construct causes no problems with the definition of the language. There's nothing in the language specification which says you can't do this. There's nothing in the C++ UnStandard Working Papers that say you can't, either. Section 6.5.3 goes on to discuss how virtual base classes work, and that demonstrates a way to have a _truly_ diamond-shaped inheritance tree. .B ekiM http://www.nwlink.com/~mikeblas/ I'm afraid I've become some sort of speed freak. These words are my own. I do not speak on behalf of Microsoft.
Gareth Jones -- gaj@i2.co.uk Monday, November 25, 1996 [Mini-digest: 4 responses] On 21 November 1996 16:11, Todd Davis[SMTP:tigger@idir.net] wrote: >> Environment: VC++ 4.1, Win 95 >> >> I'm trying to create a class which can be "mixed in" with a control to >> support special resizing functions within a CFormView. Here is an example >> of how the class is used: >> >> CWnd >> / \ >> CListCtrl CResizableCtrl >> \ / >> CMyListCtrl >> >> I could make put my CResizableCtrl functions in the control specific derived >> classes and take out the mulitple inheritance, but this seemed like such a >> slick solution. Any ideas? Am I crazy for trying to use multiple >> inheritance in the first place with MFC library classes? This isn't an answer to your specific question, rather a pointer on using MI with MFC. I have used MI reasonably extensively and successfully with MFC, but (and I can't stress this too much) ONLY for MIXIN classes. This is OK as that's what you want to do. The deal is that your mixin shouldn't derive from CWnd, CObject or any other MFC class (that's a bit f a broad generalization, but stick with me) If you have non-derived, dataless mixins , or mixins only derived from other mixin classes, and you put them second in the inheritance order (i.e. : public CWnd, public CMixinClass) then you should have very few problems. This is a very neat solution to adding enterprise-wide standard functionality to MFC control classes or dialog classes. The only slight bugbear is that C++ being what it is you can't specify what this class can be mixed into and thus can't cast across the hierarchy (i.e. from CResizable Control to CListCtrl or even CWnd). To get around this, you need to provide a pure virtual 'AccessThisAsCWnd' or similar method on your mixin, which all derived classes must implement, returning their this pointer. You obviously must comment your mixin well that it is only designed to be mixed into a CWnd-based class otherwise all hell will break loose. You can now access the CWnd side of your composite object from the Mixin. For going the other way around, you will need to do something along the lines of intercepting various OnXXXMesaage in your derived classes and forwarding them to the mixin first. This is much less elegant than the first part, but I think worth the hassle if you just want dialogs with a corporate standard behaviour or standard control's with extra methods on all. Hope this helps, Gareth -----From: Stuart DowningNot true. This is accomplished with virtual base classes. class V; class A : virtual public V; class B : virtual public V; class C : public A, public B; class C's inheritance tree looks like V / \ A B \ / C Now, whether you want to attempt this using virtual MFC bases, is another question. This is left as an exercise for the reader. :) ----- Stuart Downing sdowning@fame.com FAME Information Services, Inc. ---------- -----From: Ash Williams Todd, You're not crazy for using multiple inheritance. However there are a couple of points you need to bear in mind: 1- DO NOT multiply derive from CWnd via two classes as you are here since the windows messaging will fail. 2- The mfc runtime information won't work 100%. In fact it will only return information regarding the left-most derived class, eg CListCtrl in your diagram. The ambiguity comes from the fact that you have inherited a member function called delete via two classes (Look at the header for CObject to confirm this), and as such the compiler is entitled to complain just as it would for any other ambiguous function, hence you must provide an override. For a fuller explanation with examples see technical note 16. Good luck, Ash -----From: "Bradley V. Pohl" >-----From: "Michael S. Scherotter" >You cannot have a diamond shaped inheritance in C++ What?!? That is flat out wrong! The language does not in any way forbid this, and even provides virtual inheritence to remove extra instances of multiply-inherited common base classes. Check out section 6.5 of Bjarne Stroustroup's _The_C++_Programming_Language_, 2nd ed, to improve your knowledge of C++. --Brad Brad Pohl brad.pohl@pobox.com
| Вернуться в корень Архива |