Query Interface: Static Casting Rule

Started by
9 comments, last by Buttacup 14 years, 1 month ago
The Set of Interfaces on an Object Instance Must Be Static The set of interfaces accessible on an object through QueryInterface must be static, not dynamic. Specifically, if QueryInterface returns S_OK for a given IID once, it must never return E_NOINTERFACE on subsequent calls on the same object; and if QueryInterface returns E_NOINTERFACE for a given IID, subsequent calls for the same IID on the same object must never return S_OK. -MSDN Why is this so? Why should it not be implemented using a dynamic_cast<T*>?
-------------------------------------All my life all I ever wanted to be was, Gangsta!
Advertisement
For the first part, I expect that's because an interface is perfectly able to call QueryInterface as often as it likes to obtain another interface pointer - it's just part of the contract COM makes.

I suspect the reason it doesn't use dynamic cast is because that has some additional code overhead which it seems unnecessary to impose on a user of COM, and is COM not usable in other languages than C++? In which case you'd need to work around the dynamic cast anyway.
Tank u, Tank u o-o
-------------------------------------All my life all I ever wanted to be was, Gangsta!
You can implement it using dynamic_cast if you like. The rule isn't about static_cast vs. dynamic_cast, it simply says you can't "add" or "remove" interfaces from a running object.

This is required because of DCOM. The proxy object will cache the result of QueryInterface so that it doesn't have to do a network round-trip every time you call QueryInterface.
Quote:Original post by Codeka
You can implement it using dynamic_cast if you like. The rule isn't about static_cast vs. dynamic_cast, it simply says you can't "add" or "remove" interfaces from a running object.


Wasn't planning on it I just wondered why this statement was being made....

So none of this....

Some Header:
struct DECLSPEC_UUID("XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX") IMyInterfaceA : public IUnknown{    virtual LPCWSTR IAre();}struct DECLSPEC_UUID("XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX") IMyInterfaceB : public IUnknown{    virtual LPCWSTR IAre();}class DECLSPEC_UUID("XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX") CMyClass : public IMyInterfaceA{public:    CMyClass(){}    virtual LPCWSTR IAre(){return L"Me";};    virtual HRESULT STDMETHODCALLTYPE		QueryInterface(REFIID iid, void ** ppvObject);    virtual ULONG STDMETHODCALLTYPE		AddRef(void);    virtual ULONG STDMETHODCALLTYPE		Release(void);}


main:
    IMyInterfaceA* pIMyInterfaceA = new CMyClass;    IMyInterfaceB* pIMyInterfaceB;    pIMyInterfaceA->QueryInterface(&pIMyInterfaceB);


where QueryInterface had a dynamic_cast in it...

:D

[Edited by - Buttacup on March 10, 2010 7:36:23 AM]
-------------------------------------All my life all I ever wanted to be was, Gangsta!
Actually you cant use any kind of cast because there's no requiremwnt by COM that interfaces be implemented using inheritance. QueryInterface could in theory hit a database and try to do something
COM doesn't care what your implementation looks like. It only cares what the observable effects of the operations are. If you want to implement QueryInterface() in terms of dynamic_cast you can do that. If you want to implement QueryInterface() in terms of dancing pink poodles you can do that too. What the requirement says that if you call QueryInterface() to get an interface once on a given COM object, then any time you call QueryInterface() to get that same interface on that same COM object you always get the same result.
Quote:Original post by cache_hit
Actually you cant use any kind of cast because there's no requiremwnt by COM that interfaces be implemented using inheritance. QueryInterface could in theory hit a database and try to do something


Curious as to where this was pointing? Are you suggesting QueryInterface should be abandoned? Is there a more appropriate means of implementing QueryInterface that you feel strongly about?

-------------------------------------All my life all I ever wanted to be was, Gangsta!
You're reading to much into things. The MSDN text you quoted says absolutely nothing about dynamic_cast. Even the stuff in the text about static and dynamic is kind of a red herring. This is the important bit:

Quote:Specifically, if QueryInterface returns S_OK for a given IID once, it must never return E_NOINTERFACE on subsequent calls on the same object; and if QueryInterface returns E_NOINTERFACE for a given IID, subsequent calls for the same IID on the same object must never return S_OK.


All it's saying is that given object can't change it's mind about what is supports. It either does or doesn't. This is required so that callers have the option of holding on to an interface pointer or letting it go and asking for it again when they need it.

cache_hit's point was the same as everybody else's: exactly how you go about implementing QueryInterface is irrelevent to the question of whether or not QueryInterface can return E_NOINTERFACE. If you want to use dynamic_cast that's fine. If you want a hard-coded list of IID's that's fine too. If you want to call out to SQL to see whether or not you support a given interface then hey, knock yourself out. As long as you're consistent.
-Mike
Quote:Original post by Anon Mike
If you want to call out to SQL to see whether or not you support a given interface then hey, knock yourself out.


Thank you o-o
-------------------------------------All my life all I ever wanted to be was, Gangsta!

This topic is closed to new replies.

Advertisement