[RESOLVED] COM interface and inheritance
hello,
i have a question about Interfaces in COM
i have a Ibase interface which has a method DoBase().
i derive two classes from this base interface class CBase called
CDrived_1:CBase
CDrived_2 CBase
both class overrides Dobase Method.
CDrived_1::Dobase
{
__super::Dobase()
}
CDrived_2::Dobase
{
__super::Dobase()
}
i have a COM method which returns the Ibase Interface.
HRESULT GetInterface ( id, IBASE** pp)
{
if ( id == 0)
{
hr = CDrived_1::CreateInstance(pp);
}
if (id == 0)
{
hr = CDrived_2::CreateInstance(pp);
}
}
now in the client application if i call
IBase* pp = NUL
GetInterface (id , &pp);
pp->Dobase() //which function should be called??
i was expecting that either CDrived_1::Dobase() or CDrived_2::Dobase() should be called. since function is virtual.
but it is calling CBase::Dobase()/// Why?
how should i do it so that derived one gets called.
Regards
deepak
Re: COM interface and inheritance
hello,
now i have come up with a demo project and i am a little bit confused.
1. I created a ATL project ATLTest (EXE).
2. i added a interface IService
3. i added one method Get(IBase **ppBase ) in the Iservice Interface
4. i added Ibase ATL simple Object and added a function Test() { MessageBox(NULL. L"Base::Test",L"Base::Test",0) }
5. now added a C++ class Derived1 and added Test() function of exact same signature.
no in the client i have code like this
Code:
int _tmain(int argc, _TCHAR* argv[])
{
CoInitialize(NULL);
IServicePtr m(__uuidof(Service));
IBasePtr pbase;
m->Get(&pbase);
pbase->Test();
m = NULL;
pbase = NULL;
CoInitialize(NULL);
return 0;
}
here is the Service. cpp
Code:
CComObject<Derived1>* g_pDerived = NULL;
STDMETHODIMP CService::Get(IBase** ppbase)
{
//case1 : Calls the derived one
CComObject<Derived1> *d;
CComObject<Derived1>::CreateInstance(&d);
*ppbase = d;
return S_OK;
//Case2/:singleton : calls the derived one
if ( g_pDerived == NULL )
{
CComObject<Derived1>::CreateInstance( &g_pDerived );
*ppbase = g_pDerived;
}
//case:3 Derived1::CreateInstance (ppbase ) // this one i am using and it calls the BASE one Why??
return S_OK;
}
which approach is correct. i could get the derived class function by case 2 but is it correct.
derived1.h
Code:
#include "Base.h"
class Derived1 :public CBase
{
public:
Derived1(void);
~Derived1(void);
STDMETHOD ( Test )(void);
};
now could any body explain me how should i correct my design
regards
deepak
Re: COM interface and inheritance
Your description looks incomplete. Why don't you upload your test solution here?
And one more point. Strictly saying, you must not use case 3. As long as you return COM interface (IBase), it should have IUnknown implemented. But the latter is implemented in CComObject<> whyle Derived1 is just a template parameter for it, and must not be instantiated any other way.
1 Attachment(s)
Re: COM interface and inheritance
hello Igor,
here is the attached sample for it. it would be very nice if you could explain. i am stuck here
Case 3: Ibase has Iunknown implemented.
one more confusion i have is that when i return the interface pointer do it need to addref or client needs to. i think i need to call addref(). client would just release it. so that it would be unloaded automatically.
however i do not see any addRef() when i use Case 3. i e.
Derived1::CreateInstance (ppbase ) // does it mean that it would call addref automatically
because in all other cases (case 1 and case 2 )i saw random crashes if i do not explicitly call AddRef()
regards
d
Re: COM interface and inheritance
Quote:
Case 3: Ibase has Iunknown implemented.
Quote:
however i do not see any addRef() when i use Case 3.
:) Something makes me think that in case 3 there is no IUnknown implemented. Otherwise you would see AddRef alright. This exactly is what I was talking about.
Re: COM interface and inheritance
hello Igor.
:)
Ibase is the standard ATL object. it is derived from CComObjectRootEx which provides Iunknown implementation.
am i correct here? still confused about cases and difference among them.
regards
Deepak
Re: COM interface and inheritance
Okay, about your original question.
Quote:
Code:
//case1 : Calls the derived one
CComObject<Derived1> *d;
CComObject<Derived1>::CreateInstance(&d);
*ppbase = d;
This makes compiler to call this:
Code:
template <class Base>
HRESULT WINAPI CComObject<Base>::CreateInstance(CComObject<Base>** pp) throw()
{
ATLASSERT(pp != NULL);
if (pp == NULL)
return E_POINTER;
*pp = NULL;
HRESULT hRes = E_OUTOFMEMORY;
CComObject<Base>* p = NULL;
ATLTRY(p = new CComObject<Base>())
if (p != NULL)
{
p->SetVoid(NULL);
p->InternalFinalConstructAddRef();
hRes = p->_AtlInitialConstruct();
if (SUCCEEDED(hRes))
hRes = p->FinalConstruct();
if (SUCCEEDED(hRes))
hRes = p->_AtlFinalConstruct();
p->InternalFinalConstructRelease();
if (hRes != S_OK)
{
delete p;
p = NULL;
}
}
*pp = p;
return hRes;
}
All seems perfect. Your Derived1 class is correctly passed for instance creation, that's why you have correct Test method. And automatic AddRef as well. :)
Now about more tricky thing.
Quote:
Code:
//case:3 Derived1::CreateInstance (ppbase ) // this one i am using and it calls the BASE one Why??
This makes compiler to call this:
Code:
template <class T, const CLSID* pclsid = &CLSID_NULL>
class CComCoClass
{
. . .
template <class Q>
static HRESULT CreateInstance(Q** pp)
{
return T::_CreatorClass::CreateInstance(NULL, __uuidof(Q), (void**) pp);
}
};
Now, it's totally different call that instantiates the class that is bound to IBase GUID, which is... right, CBase. :)
And please disregard my other comments about IUnknown, as I was wrong.