aboutsummaryrefslogtreecommitdiff
path: root/files/zh-cn/implementing_queryinterface/index.html
diff options
context:
space:
mode:
Diffstat (limited to 'files/zh-cn/implementing_queryinterface/index.html')
-rw-r--r--files/zh-cn/implementing_queryinterface/index.html172
1 files changed, 0 insertions, 172 deletions
diff --git a/files/zh-cn/implementing_queryinterface/index.html b/files/zh-cn/implementing_queryinterface/index.html
deleted file mode 100644
index 6fe9761e22..0000000000
--- a/files/zh-cn/implementing_queryinterface/index.html
+++ /dev/null
@@ -1,172 +0,0 @@
----
-title: 实现QueryInterface接口
-slug: Implementing_QueryInterface
-translation_of: Mozilla/Implementing_QueryInterface
----
-<p><font><font>本文档介绍正确地实现</font></font><code>QueryInterface()</code><font><font>的方式 </font></font><font><font>。</font></font></p>
-
-<h3 id="A_reference_implementation_of_QueryInterface" name="A_reference_implementation_of_QueryInterface">QueryInterface的参考实现</h3>
-
-<pre class="eval">NS_IMETHODIMP
-nsMyImplementation::QueryInterface( REFNSIID aIID, void** aInstancePtr )
- {
- NS_ASSERTION(aInstancePtr, "QueryInterface requires a non-NULL destination!");
- <span class="comment">// It's a logic error, not a runtime error, to call me without any place to put my answer!</span>
-
- <span class="comment">// ...but that won't matter when someone calls me wrongly in a non-debug build.</span>
- if ( !aInstancePtr )
- return NS_ERROR_NULL_POINTER;
-
- nsISupports* foundInterface;
-
- if ( aIID.Equals(nsCOMTypeInfo&lt;nsIX&gt;::GetIID()) )
- foundInterface = NS_STATIC_CAST(nsIX*, this);
- else if ( aIID.Equals(nsCOMTypeInfo&lt;nsIY&gt;::GetIID()) )
- foundInterface = NS_STATIC_CAST(nsIY*, this);
-
- <span class="comment">// ...as many cases as needed...</span>
-
- else if ( aIID.Equals(nsCOMTypeInfo&lt;nsISupports&gt;::GetIID()) )
- foundInterface = NS_STATIC_CAST(nsISupports*, NS_STATIC_CAST(nsIX*, this));
- <span class="comment">// I (may) have multiple |nsISupports| in me,
- // so first I cast to a specific base to avoid ambiguity</span>
- else
- foundInterface = 0;
-
-
- nsresult status;
- if ( !foundInterface )
- status = NS_NOINTERFACE;
- else
- {
- NS_ADDREF(foundInterface);
- status = NS_OK;
- }
-
- *aInstancePtr = foundInterface;
- return status;
- }
-
-</pre>
-
-<h3 id="What.27s_So_Good_About_It.3F" name="What.27s_So_Good_About_It.3F">有什么好处呢?</h3>
-
-<p>代码优点:</p>
-
-<ul>
- <li><font><font>简单明了。</font></font></li>
- <li>好的。它有多个 <code>return</code>,但正如预期的那样,主要的 <code>return</code> 位于函数的末尾;并且附加的 <code>return</code>清晰而单独地位于函数的顶部。</li>
- <li><font><font>它只有一个</font></font><code>AddRef</code><font><font>。</font></font></li>
- <li><code>AddRef</code><font><font>是生成的接口,不是</font></font><code>this</code><font><font>,因此遵循 COM 正确的方式(在聚合中尤其重要)</font></font></li>
- <li><font><font>它使用</font></font><code>nsCOMTypeInfo&lt;T&gt;::GetIID()</code><font><font>而不是</font></font><code>kTIID</code><font><font>节省全局声明和全局空间</font></font></li>
- <li><font><font>它使用C的</font></font><code>NS_STATIC_CAST </code>定义<code>的</code><code>static_cast</code><font><font>,</font></font><font><font>当您无法真正获得所需的接口时,它将检测错误。</font></font></li>
- <li><font><font>它避免了反复使用和分配给</font></font><code>*aInstancePtr</code><font><font>,这些会使编译器在优化时遇到麻烦。</font></font></li>
- <li><code>*aInstancePtr</code><font><font>返回错误时</font><font>,将清除结果</font><font>。</font></font></li>
- <li><font><font>与通常的</font></font><code>QueryInterface</code><font><font>实现相比,它生成的代码更少</font></font><font><font>。</font></font></li>
- <li>它使用<code>NS_ASSERTION</code>测试错误输入,以便在调试构建中立即发现逻辑错误</li>
-</ul>
-
-<h3 id="Some_Alternatives" name="Some_Alternatives">一些替代方案</h3>
-
-<h4 id="The_NS_IMPL_QUERY_INTERFACE.5B012.5D_macros" name="The_NS_IMPL_QUERY_INTERFACE.5B012.5D_macros"><code>NS_IMPL_QUERY_INTERFACE</code>[<code>012</code>] 宏</h4>
-
-<p>除了<code>nsISupports</code>外,上面的示例还实现了两个{{ mediawiki.external('XP') }} COM接口。<code>NS_IMPL_QUERY_INTERFACE2</code>宏可以为您编写此函数(尽管我很难推荐宏),例如,</p>
-
-<pre class="eval">NS_IMPL_QUERY_INTERFACE2(nsMyImplementation, nsIX, nsIY)
- <span class="comment">// implements |nsMyImplementation::QueryInterface| as above</span>
-
-NS_IMPL_QUERY_INTERFACE1(nsFoo, nsIFoo) <span class="comment">// |nsFoo::QueryInterface| provides |nsIFoo| and |nsISupports|</span>
-NS_IMPL_QUERY_INTERFACE0(nsBar) <span class="comment">// |nsBar::QueryInterface| can only provide an |nsISupports|</span>
-</pre>
-
-<p>同样,当仅实现一个附加接口时,可以使用宏<code>NS_IMPL_QUERY_INTERFACE1</code>;当仅实现<code>nsISupports</code>时,可以使用宏<code>NS_IMPL_QUERY_INTERFACE0</code> 。如果使用<code>NS_IMPL_ISUPPORTS*</code>宏,将为您调用这些宏,这些宏提供相应的<code>QueryInterface</code> 实现,以及<code>AddRef</code> 和<code>Release</code>。</p>
-
-<h4 id="Calling_an_inherited_QueryInterface" name="Calling_an_inherited_QueryInterface">调用继承的 <code>QueryInterface</code></h4>
-
-<p>有时,您只是将一个或两个新接口添加到已经支持许多其他接口的实现中。在这种情况下,在测试了所关心的特定<code>IID</code>之后,您可能希望调用底层实现。这节省了代码空间并降低了复杂性。下面的代码突出显示了这些差异。</p>
-
-<pre><code>class nsMyImplmentation : public nsBaseImplementation, public nsIX, public nsIY { ... };
-
-NS_IMETHODIMP
-nsMyImplementation::QueryInterface( REFNSIID aIID, void** aInstancePtr )
- /*
- I just add the interfaces |nsIX| and |nsIY|.
- My base class |nsBaseImplementation| provides all the rest.
- */
- {
- NS_ASSERTION(aInstancePtr, "QueryInterface requires a non-NULL destination!");
-
- if ( !aInstancePtr )
- return NS_ERROR_NULL_POINTER;
-
- nsISupports* foundInterface;
-
- if ( aIID.Equals(nsCOMTypeInfo&lt;nsIX&gt;::GetIID()) )
- foundInterface = NS_STATIC_CAST(nsIX*, this);
- else if ( aIID.Equals(nsCOMTypeInfo&lt;nsIY&gt;::GetIID()) )
- foundInterface = NS_STATIC_CAST(nsIY*, this);
- // Note: Don't check for |nsISupports|; |nsBaseImplementation| will do that for me.
- else
- foundInterface = 0;
-
-
- nsresult status;
- if ( !foundInterface )
- // OK, _I_ didn't find an interface. Maybe my base class can.
- status = nsBaseImplementation::QueryInterface(aIID, &amp;foundInterface);
- else
- {
- NS_ADDREF(foundInterface);
- status = NS_OK;
- }
-
- *aInstancePtr = foundInterface;
- return status;
- }</code>
-</pre>
-
-<p>请注意,如果 base实现 的 <code>QueryInterface</code>找到了适当的接口,则你的<code>QueryInterface</code> 不能 <code>AddRef</code> 它。这反映在上面的代码中。<br>
- <br>
- 这种技术之所以有效,是因为 <code>nsBaseImplementation</code> 已经是一个可以单独使用的完整类。当你从几个完整的类派生时,这种技术不太合适;但如果您对顺序敏感,则仍然可以使用它,例如,</p>
-
-<pre><code>// ...
- nsresult status;
- if ( !foundInterface )
- {
- // OK, ask |nsBase1Imp| first, because I want _it_ to be the one true |nsISupports|.
- status = nsBase1Imp::QueryInterface(aIID, &amp;foundInterface);
-
- if ( !foundInterface )
- status = nsBase2Imp::QueryInterface(aIID, &amp;foundInterface);
-
- if ( !foundInterface )
- status = nsBase3Imp::QueryInterface(aIID, &amp;foundInterface);
- }
- else
- {
- NS_ADDREF(foundInterface);
- status = NS_OK;
- }
- // ...</code>
-</pre>
-
-<p>如果您的任何基类参与真正的聚合,那么要把正确的事情做好 即使不是不可能,也是很困难的。您将不能在聚合对象上获得对 <code>QueryInterface</code> 的调用,这可能会返回错误的接口。这也是一个需要特别避免 聚合和复杂的层次结构 的原因。</p>
-
-<h4 id="The_NS_GET_IID_macro" name="The_NS_GET_IID_macro"><code>NS_GET_IID</code> 宏</h4>
-
-<p>您可以使用·<code>NS_GET_IID</code> 宏,而不是键入完整的<code>GetIID </code>表达式。一般来说,我不赞成宏,除非在不同的情况下宏必须扩展为不同的文本,例如,不同的平台,调试与非调试,等等。在这种情况下,宏是必不可少的。在其他情况下,宏可能会帮助一些人,但通常会给其他人带来模糊的问题。它们总是使程序源更加脆弱。在这种情况下,宏只是为了方便起见,所以我不推荐它,但我确实提供了它作为替代。</p>
-
-<pre><code>// ...
- if ( aIID.Equals(NS_GET_IID(nsIX)) )
- foundInterface = NS_STATIC_CAST(nsIX*, this);
- else if ( aIID.Equals(NS_GET_IID(nsIY)) )
- foundInterface = NS_STATIC_CAST(nsIY*, this);
-
- // ...as many cases as needed...
-
- else if ( aIID.Equals(NS_GET_IID(nsISupports)) )
- // ...</code></pre>
-
-<h3 id="Thanks" name="Thanks">Thanks</h3>
-
-<p>特别感谢 <a href="mailto:heikki@citec.fi">Heikki Toivonen</a>, <a href="mailto:waterson@netscape.com">Chris Waterson</a>和<a href="mailto:jband@netscape.com">John Bandhauer</a> 提供的宝贵反馈,这些反馈极大地改进了这里提供的实现</p>