<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.msdn.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>jeff's WebLog : COM</title><link>http://blogs.msdn.com/jeffdav/archive/tags/COM/default.aspx</link><description>Tags: COM</description><dc:language>en-US</dc:language><generator>CommunityServer 2.1 SP1 (Build: 61025.2)</generator><item><title>on CComQIPtr</title><link>http://blogs.msdn.com/jeffdav/archive/2007/04/10/on-ccomqiptr.aspx</link><pubDate>Wed, 11 Apr 2007 01:21:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:2078393</guid><dc:creator>jeffdav</dc:creator><slash:comments>4</slash:comments><comments>http://blogs.msdn.com/jeffdav/comments/2078393.aspx</comments><wfw:commentRss>http://blogs.msdn.com/jeffdav/commentrss.aspx?PostID=2078393</wfw:commentRss><description>&lt;P&gt;You're writing some code that uses COM.&amp;nbsp; Do you use SmartPointers or not use&amp;nbsp;SmartPointers?&amp;nbsp; Debate on this topic flares up now and then.&amp;nbsp; &lt;/P&gt;
&lt;P&gt;The trick to answering it is to seperate the technical facts from stubbornly held beliefs.&amp;nbsp; Like any technology, there is a right time and a wrong time to use it.&amp;nbsp; But that's not what I want to talk about today.&amp;nbsp; Let's assume you've decided to use SmartPointers.&amp;nbsp; I posit that CComPtr&amp;lt;&amp;gt; is good and CComQIPtr&amp;lt;&amp;gt; is bad.&lt;/P&gt;
&lt;P&gt;The reason for this is simple: CComQIPtr&amp;lt;&amp;gt; masks the return value of the QueryInterface() call.&amp;nbsp; &lt;/P&gt;
&lt;P&gt;Lets take a look at two snippets of code to frame the discussion:&lt;/P&gt;
&lt;P&gt;
&lt;TABLE class="" style="DISPLAY: inline; FONT-SIZE: 1em; BORDER-COLLAPSE: collapse" border=1&gt;
&lt;TBODY&gt;
&lt;TR&gt;
&lt;TD class=ms-rtetablecells style="VERTICAL-ALIGN: top" class="ms-rtetablecells"&gt;
&lt;DIV&gt;&lt;FONT face="Courier New"&gt;void ExFunc(IFoo *pFoo)&lt;/FONT&gt;&lt;/DIV&gt;
&lt;DIV&gt;&lt;FONT face="Courier New"&gt;{&lt;/FONT&gt;&lt;/DIV&gt;
&lt;DIV&gt;&lt;FONT face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; HRESULT hr = pFoo-&amp;gt;Init();&lt;/FONT&gt;&lt;/DIV&gt;
&lt;DIV&gt;&lt;FONT face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (SUCCEEDED(hr))&lt;/FONT&gt;&lt;/DIV&gt;
&lt;DIV&gt;&lt;FONT face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/FONT&gt;&lt;/DIV&gt;
&lt;DIV&gt;&lt;FONT face="Courier New" color=#008000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; CComPtr&amp;lt;IBar&amp;gt; spBar;&lt;/FONT&gt;&lt;/DIV&gt;
&lt;DIV&gt;&lt;FONT face="Courier New" color=#008000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; hr = pfoo-&amp;gt;QueryInterface(IID_PPV_ARGS(spBar));&lt;/FONT&gt;&lt;/DIV&gt;
&lt;DIV&gt;&lt;FONT face="Courier New" color=#008000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (SUCCEEDED(hr))&lt;/FONT&gt;&lt;/DIV&gt;
&lt;DIV&gt;&lt;FONT face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/FONT&gt;&lt;/DIV&gt;
&lt;DIV&gt;&lt;FONT face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; hr = spBar-&amp;gt;DoSomething();&lt;/FONT&gt;&lt;/DIV&gt;
&lt;DIV&gt;&lt;FONT face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/FONT&gt;&lt;/DIV&gt;
&lt;DIV&gt;&lt;FONT face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/FONT&gt;&lt;/DIV&gt;
&lt;DIV&gt;&lt;FONT face="Courier New"&gt;}&lt;/FONT&gt;&lt;/DIV&gt;&lt;/TD&gt;
&lt;TD class=ms-rtetablecells style="VERTICAL-ALIGN: top" class="ms-rtetablecells"&gt;
&lt;DIV&gt;
&lt;DIV&gt;&lt;FONT face="Courier New"&gt;void ExFunc(IFoo *pFoo)&lt;/FONT&gt;&lt;/DIV&gt;
&lt;DIV&gt;&lt;FONT face="Courier New"&gt;{&lt;/FONT&gt;&lt;/DIV&gt;
&lt;DIV&gt;&lt;FONT face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; HRESULT hr = pFoo-&amp;gt;Init();&lt;/FONT&gt;&lt;/DIV&gt;
&lt;DIV&gt;&lt;FONT face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (SUCCEEDED(hr))&lt;/FONT&gt;&lt;/DIV&gt;
&lt;DIV&gt;&lt;FONT face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/FONT&gt;&lt;/DIV&gt;
&lt;DIV&gt;&lt;FONT face="Courier New" color=#ff0000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; hr = E_NOINTERFACE;&lt;/FONT&gt;&lt;/DIV&gt;
&lt;DIV&gt;&lt;FONT face="Courier New" color=#ff0000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; CComQIPtr&amp;lt;IBar&amp;gt; spBar = pFoo;&lt;/FONT&gt;&lt;/DIV&gt;
&lt;DIV&gt;&lt;FONT face="Courier New" color=#ff0000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (spBar)&lt;/FONT&gt;&lt;/DIV&gt;
&lt;DIV&gt;&lt;FONT face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/FONT&gt;&lt;/DIV&gt;
&lt;DIV&gt;&lt;FONT face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; hr = spBar-&amp;gt;DoSomething();&lt;/FONT&gt;&lt;/DIV&gt;
&lt;DIV&gt;&lt;FONT face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/FONT&gt;&lt;/DIV&gt;
&lt;DIV&gt;&lt;FONT face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/FONT&gt;&lt;/DIV&gt;
&lt;DIV&gt;&lt;FONT face="Courier New"&gt;}&lt;/FONT&gt;&lt;/DIV&gt;&lt;/DIV&gt;&lt;/TD&gt;&lt;/TR&gt;&lt;/TBODY&gt;&lt;/TABLE&gt;&lt;/P&gt;
&lt;P&gt;Some points:&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;When you have a large number of people working on the same code base, you want to create patterns in the code that people recognize.&amp;nbsp; CComQIPtr&amp;lt;&amp;gt; breaks the pattern of COM-call/check-HRESULT.&amp;nbsp; Instead you have to check for the non-NULLness of the out parameter.&amp;nbsp; &lt;/LI&gt;
&lt;LI&gt;You can assume the QueryInterface() call failed with E_NOINTERFACE, but you don't know for sure.&amp;nbsp; What if it failed with some other HRESULT?&amp;nbsp; Nobody says QueryInterface() can't do things besides just casting this around.&amp;nbsp; E.g. a function that implements IPersistFile::Load() could delay loading the file until someone does a QueryInterface() for an interface that actually needs the contents of the file it was asked to load.&lt;/LI&gt;
&lt;LI&gt;CComQIPtr&amp;lt;&amp;gt; masks errors in QueryInterface().&amp;nbsp; The contract for QueryInterface() is the out parameter must be valid if it returns success, otherwise it must be set to NULL.&amp;nbsp; So, in theory, if (SUCCEEDED(hr)) { ... } and if (spBar) { ... } should be equivalent.&amp;nbsp; However, people often &lt;A class="" href="http://blogs.msdn.com/oldnewthing/archive/2004/03/26/96777.aspx" mce_href="http://blogs.msdn.com/oldnewthing/archive/2004/03/26/96777.aspx"&gt;get QueryInterface() wrong&lt;/A&gt;.&amp;nbsp; It seems to me that it is much more likely an implementer will fail to set the out parameter to NULL on failure than they will fail to return S_OK on success.&lt;/LI&gt;
&lt;LI&gt;Lastly, I just don't like the fact that magic is happening in the assignment.&amp;nbsp; It is easy to screw things up with COM, and it seems CComQIPtr&amp;lt;&amp;gt; just makes it easier.&amp;nbsp; CComPtr&amp;lt;&amp;gt; is a lot less magic and more predictable.&amp;nbsp; It makes it harder to screw things up.&lt;/LI&gt;&lt;/OL&gt;
&lt;P&gt;In summary: use CComPtr&amp;lt;&amp;gt; and don't use CComQIPtr&amp;lt;&amp;gt;.&amp;nbsp;&amp;nbsp;I would especially encourage those who would&amp;nbsp;write Internet Explorer extensions to&amp;nbsp;use CComPtr&amp;lt;&amp;gt;.&amp;nbsp; &lt;/P&gt;
&lt;P&gt;Thoughts?&amp;nbsp;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=2078393" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/jeffdav/archive/tags/internet+explorer/default.aspx">internet explorer</category><category domain="http://blogs.msdn.com/jeffdav/archive/tags/COM/default.aspx">COM</category></item></channel></rss>