CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 7 of 7
  1. #1
    Join Date
    Jan 2007
    Posts
    90

    [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:obase
    {
    __super:obase()
    }

    CDrived_2:obase
    {
    __super:obase()
    }

    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:obase() or CDrived_2:obase() should be called. since function is virtual.
    but it is calling CBase:obase()/// Why?

    how should i do it so that derived one gets called.

    Regards
    deepak

  2. #2
    Join Date
    Jan 2007
    Posts
    90

    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
    Last edited by Deepak_Sharma; December 1st, 2009 at 11:36 AM. Reason: formating

  3. #3
    Join Date
    Nov 2000
    Location
    Voronezh, Russia
    Posts
    6,633

    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.
    Best regards,
    Igor

  4. #4
    Join Date
    Jan 2007
    Posts
    90

    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
    Attached Files Attached Files

  5. #5
    Join Date
    Nov 2000
    Location
    Voronezh, Russia
    Posts
    6,633

    Re: COM interface and inheritance

    Case 3: Ibase has Iunknown implemented.
    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.
    Last edited by Igor Vartanov; December 3rd, 2009 at 06:16 PM.
    Best regards,
    Igor

  6. #6
    Join Date
    Jan 2007
    Posts
    90

    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

  7. #7
    Join Date
    Nov 2000
    Location
    Voronezh, Russia
    Posts
    6,633

    Re: COM interface and inheritance

    Okay, about your original question.

    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.

    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.
    Best regards,
    Igor

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured