15 мая 2023 года "Исходники.РУ" отмечают своё 23-летие!
Поздравляем всех причастных и неравнодушных с этим событием!
И огромное спасибо всем, кто был и остаётся с нами все эти годы!

Главная Форум Журнал Wiki DRKB Discuz!ML Помощь проекту


MFC macro strangeness with multiple inheritance

Paul.B.Folbrecht@JCI.Com
Wednesday, October 16, 1996

     Environment: Win95, Visual C++ 4.1 
     
     OK, here's a really strange item.
     
     The situation:  I have a simple, abstract mixin class with a single 
     pure virtual function, as so:
     
     class CNotify
     {
        public:
                virtual void OnEvent() = 0;
     };
     
     I also have a dialog class, multiple derived from both CDialog and 
     CNotify:
     
     class CMyDialog : public CDialog, public CNotify
     
     From another class, I call the dialog's OnEvent() method, which of 
     course it has defined.  What happens?  It goes not to OnEvent, but to 
     the IMPLEMENT_DYNAMIC macro, specifically to GetRuntimeClass(), then 
     returns without ever hitting OnEvent.  
     
     I know MFC can be finicky with multiple inheritance, but there's 
     nothing here that should cause a problem.  I'm not completing any 
     diamond which I know is a no-no with MFC.  Incidentally, I've tried 
     reversing the order of the base classes in the CMyDialog declaration, 
     and this causes the dialog to fail to work completely, blowing up on 
     creation.  I'v tried doing full builds to no avail.
     
     -Paul Folbrecht,
     Compuware Corp.



Mario Contestabile -- Mario_Contestabile.UOS__MTL@UOSMTL2.universal.com
Friday, October 18, 1996

[Mini-digest: 3 responses]

>From another class, I call the dialog's OnEvent() method, which of 
>     course it has defined.  What happens?  It goes not to OnEvent, but to 
>     the IMPLEMENT_DYNAMIC macro

Why isn't the code snippet for the virtual function call included with the 
question?

mcontest@universal.com

-----From: Mike Kurtinitis 

Hi Paul,

I recently experienced the *exact* problem you've described. I found the
solution to lie in the way pointers are casted.  My bet is you're doing
something like this:

CSomeClass theClass;
CDialog* pDlg;

pDlg = m_pMyDlg;        // m_pMyDlg is an instance of CMyDialog
theClass.StoreDialog((CNotify*)pDlg);

Later on some other code inside CSomeClass does the following:

m_pStoredDlg->OnEvent();        // Jumps to the top of the file

To remedy this, pass a CMyDialog* instead of  a CDialog* to StoreDialog() .
The wrong VTABLE is being used to look up the OnNotify() call. By properly
casting the pointer you can insure the correct VTABLE is used.

I'd be glad to look at the actual snippet of code that is causing you
problems if what I described isn't the culprit.

Good Luck,

-Mike Kurtinitis
Mooshwerks
moosh@halcyon.com

At 08:43 AM 10/16/96 -0600, you wrote:
>     Environment: Win95, Visual C++ 4.1 
>     
>     OK, here's a really strange item.
>     
>     The situation:  I have a simple, abstract mixin class with a single 
>     pure virtual function, as so:
>     
>     class CNotify
>     {
>        public:
>                virtual void OnEvent() = 0;
>     };
>     
>     I also have a dialog class, multiple derived from both CDialog and 
>     CNotify:
>     
>     class CMyDialog : public CDialog, public CNotify
>     
>     From another class, I call the dialog's OnEvent() method, which of 
>     course it has defined.  What happens?  It goes not to OnEvent, but to 
>     the IMPLEMENT_DYNAMIC macro, specifically to GetRuntimeClass(), then 
>     returns without ever hitting OnEvent.  
>     
>     I know MFC can be finicky with multiple inheritance, but there's 
>     nothing here that should cause a problem.  I'm not completing any 
>     diamond which I know is a no-no with MFC.  Incidentally, I've tried 
>     reversing the order of the base classes in the CMyDialog declaration, 
>     and this causes the dialog to fail to work completely, blowing up on 
>     creation.  I'v tried doing full builds to no avail.
>     
>     -Paul Folbrecht,
>     Compuware Corp.
>
>

-----From: Kostya Sebov 

You must be using the pattern:

void CMyControl::OnSomething()
{

    CNotify* pToBeNotified = (CNotify*)GetParent();

    pToBeNoftified->OnEvent(); // here's the trap
}

You should code:
    CNotify* pToBeNotified = (CMyDialog*)GetParent();

to allow the compiler correctly resolve pointers to v-tables.

HTH

--- 
Kostya Sebov. 
----------------------------------------------------------------------------
Tel: (38 044) 266-6387 | Fax: (38 044) 266-6195 | E-mail: sebov@is.kiev.ua



CBYRNEHAM@derwent.co.uk
Tuesday, October 22, 1996

[Mini-digest: 3 responses]

     Environment: Win95, Visual C++ 4.2
     
     You've probably fixed it by now... Its a shame you chose the name 
     OnEvent as thats already defined in CCmdTarget. ( From which CDialog 
     is of course derived ) 
     Did your original OnEvent have some parameters ??
     
     With the no parameter version you describe it compiles and runs O.K. 
     on 4.2
     
     Have you tried using a different function name    :)
     
     Best regards,
                Chris Byrneham.
-----From: Paul.B.Folbrecht@JCI.Com


     Yes, I fixed it by changing the direct cast to (CNotify*) I was using 
     to a dynamic_cast.  I should've known the direct cast is a no-no when 
     multiple inheritance is involved.  Also, OnEvent was not the actual 
     name I was using.
     
     -Paul

-----From: Paul.B.Folbrecht@JCI.Com


     To all who replied to this problem:
     
     The problem was indeed caused by mismatched vtables.  My original call 
     (sorry for not including that) was like this:
     
     CNotify* pDlg = (CNotify*) ...
     
     Changing the straight cast to dynamic_cast causes the runtime system 
     to supply the correct pointer.  
     
     -Paul
     
-----From: Mike Kurtinitis 
     
Hi Paul,
     
I recently experienced the *exact* problem you've described. I found the 
solution to lie in the way pointers are casted.  My bet is you're doing 
something like this:
     
CSomeClass theClass;
CDialog* pDlg;
     
pDlg = m_pMyDlg;        // m_pMyDlg is an instance of CMyDialog 
theClass.StoreDialog((CNotify*)pDlg);
     
Later on some other code inside CSomeClass does the following:
     
m_pStoredDlg->OnEvent();        // Jumps to the top of the file
     
To remedy this, pass a CMyDialog* instead of  a CDialog* to StoreDialog() . 
The wrong VTABLE is being used to look up the OnNotify() call. By properly 
casting the pointer you can insure the correct VTABLE is used.
     
I'd be glad to look at the actual snippet of code that is causing you 
problems if what I described isn't the culprit.
     
Good Luck,
     
-Mike Kurtinitis
Mooshwerks
moosh@halcyon.com
     
-----From: Kostya Sebov 
     
You must be using the pattern:
     
void CMyControl::OnSomething()
{
     
    CNotify* pToBeNotified = (CNotify*)GetParent();
     
    pToBeNoftified->OnEvent(); // here's the trap
}
     
You should code:
    CNotify* pToBeNotified = (CMyDialog*)GetParent();
     
to allow the compiler correctly resolve pointers to v-tables.
     
HTH
     
---
Kostya Sebov.
---------------------------------------------------------------------------- 
Tel: (38 044) 266-6387 | Fax: (38 044) 266-6195 | E-mail: sebov@is.kiev.ua




| Вернуться в корень Архива |