Windows 当传递的对象不';不实现必要的接口?

Windows 当传递的对象不';不实现必要的接口?,windows,visual-c++,com,error-handling,Windows,Visual C++,Com,Error Handling,在COM中,当我拥有无法更改的知名接口时: interface IWellKnownInterface { HRESULT DoStuff( IUnknown* ); }; 我的IWellKnownInterface::DoStuff()实现只能在传递的对象实现某些特定接口时才能工作。我如何处理这种情况 HRESULT CWellKnownInterfaceImpl::DoStuff( IUnknown* param ) { //this will QI for the sp

在COM中,当我拥有无法更改的知名接口时:

interface IWellKnownInterface {
     HRESULT DoStuff( IUnknown* );
};
我的IWellKnownInterface::DoStuff()实现只能在传递的对象实现某些特定接口时才能工作。我如何处理这种情况

HRESULT CWellKnownInterfaceImpl::DoStuff( IUnknown* param )
{
    //this will QI for the specific interface        
    ATL::CComQIPtr<ISpecificInterface> object( param );
    if( object == 0 )
        //clearly the specifil interface is not supported
        return E_INVALIDARG;
    }
    // proceed with implementation
}
HRESULT CWellKnownInterfaceImpl::DoStuff(IUnknown*param)
{
//这将为特定接口提供QI
ATL::CComQIPtr对象(param);
如果(对象==0)
//显然,不支持指定接口
返回E_INVALIDARG;
}
//着手实施
}

如果不支持特定接口,我应该返回哪个错误代码?返回E_INVALIDARG是否合适?

是。至少,在这种情况下,我学会了期待microsoft API调用返回

是的。至少,在这种情况下,我学会了期待microsoft API调用返回

E_INVALIDARG
是一个不错的选择,但最重要的是确保您使用的每个返回代码的精确条件都有很好的文档记录


另外,您可以考虑实现和然后通过和返回。这在您认为调用方可能受益于在故障点生成自定义错误消息以及其中包含的所有相关上下文的情况下尤其有用。在您的情况下,这可能是为了明确指出哪个参数是无效的,哪个接口是未实现的。即使这样的消息不太可能对最终用户有价值,但如果它显示在日志文件或事件查看器中,对开发人员来说可能是非常宝贵的。

E_INVALIDARG
是一个不错的选择,但最重要的是确保您使用的每个返回代码的精确条件都有很好的文档记录

另外,您可以考虑实现和然后通过和返回。这在您认为调用方可能受益于在故障点生成自定义错误消息以及其中包含的所有相关上下文的情况下尤其有用。在您的情况下,这可能是为了明确指出哪个参数是无效的,哪个接口是未实现的。即使这样的消息不太可能对最终用户有价值,但如果它出现在日志文件或事件查看器中,对开发人员来说可能是非常宝贵的。

我不同意这种说法
E_NOINTERFACE
具有非常具体的含义,即您的对象不支持您的客户刚刚请求的特定接口

通常,您应该只从自己的
IUnknown::QueryInterface()
返回
E\u NOINTERFACE
。从
DoStuff()
返回
E\u-NOINTERFACE
,最终用户和工具都会感到惊讶。如果我看到
E\u NOINTERFACE
来自
QueryInterface()
以外的任何地方,我的第一反应就是“抽象泄漏!”

乍一看,
E_INVALIDARG
似乎是最好的选择——毕竟,你被传递了一个不适合你的论点。但在我看来,这里有一个微妙之处,所以我不确定我是否能从中得出一个普遍的规则

在理想情况下,COM方法返回的错误代码更多地与接口有关,而不是与对象有关。具体地说,
IWellKnownInterface::DoStuff()
没有定义(必须)传入的对象必须实现
isSpecificInterface
,否则它将具有不同的参数类型。因此,从技术上讲,您没有完全实现接口的语义,这是在欺骗对象的潜在用户。当然,在现实世界中,如果你把它变成一个绝对的规则,并且接口是如此严格,那么很难创建一个有意义的开放系统

SO:如果您提供的功能仍然满足接口语义,即使您的参数没有实现“代码> ISCOMPICION接口< /代码>,您也应该考虑这样做。

假设您必须返回错误:如果这是一个众所周知、记录良好(设计良好?)的界面,我可能会首先浏览一下界面文档,看看它们是否给您提供了任何指导。如果没有这些,我可能会继续使用
E_INVALIDARG

对于如何向用户提供有关错误性质的更多信息,有一些很好的建议

显然,如果您有机会,您可能希望更改接口,改为使用
isSpecificInterface*param

我不同意您的看法
E_NOINTERFACE
具有非常具体的含义,即您的对象不支持您的客户刚刚请求的特定接口

通常,您应该只从自己的
IUnknown::QueryInterface()
返回
E\u NOINTERFACE
。从
DoStuff()
返回
E\u-NOINTERFACE
,最终用户和工具都会感到惊讶。如果我看到
E\u NOINTERFACE
来自
QueryInterface()
以外的任何地方,我的第一反应就是“抽象泄漏!”

乍一看,
E_INVALIDARG
似乎是最好的选择——毕竟,你被传递了一个不适合你的论点。但在我看来,这里有一个微妙之处,所以我不确定我是否能从中得出一个普遍的规则

在理想情况下,COM方法返回的错误代码更多地与接口有关,而不是与对象有关。具体地说,
IWellKnownInterface::DoStuff()
没有定义(必须)传入的对象必须实现
isSpecificInterface
,否则它将具有不同的参数类型。因此,从技术上讲,您没有完全实现接口的语义,这是在欺骗对象的潜在用户。当然,在现实世界中,这是很难创造的