Sign in to follow this  

Query Interface: Static Casting Rule

This topic is 2835 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

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*>?

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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]

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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?

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites
Quote:
Original post by Anon Mike
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.


and hey I didn't catch myself on that one....

Share this post


Link to post
Share on other sites

This topic is 2835 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this