【问题标题】:ATL COM - How To Reuse Code for Interface MethodATL COM - 如何重用接口方法的代码
【发布时间】:2012-05-28 05:43:03
【问题描述】:

我有几个接口,例如IA、IB、IC 等,它们具有共同的属性,例如地点。我想知道如何重用这些接口的代码(请把关于 COM 聚合的答案留给我)。

目前的实现如下:

class CA
// ATL specific...
{
    STDMETHODIMP get_Site(...) {...}
    STDMETHODIMP put_Site(...) {...}
}

class BA
// ATL specific...
{
    STDMETHODIMP get_Site(...) {...}
    STDMETHODIMP put_Site(...) {...}
}

class CC
// ATL specific...
{
    STDMETHODIMP get_Site(...) {...}
    STDMETHODIMP put_Site(...) {...}
}

我想要(但不能)实现的目标如下。

template<typename T>
class SharedProperties
{
    STDMETHODIMP get_Site(...) {...}
    STDMETHODIMP put_Site(...) {...}
}

class CA :
// ATL specific...
SharedProperties<CA>
{
    // properties are inherited and are accessible from IC
}

class BA
// ATL specific...
SharedProperties<CB>
{
    // properties are inherited and are accessible from IB
}

class CC
// ATL specific...
SharedProperties<CC>
{
// properties are inherited and are accessible from IA
}

我在阅读 (http://vcfaq.mvps.org/com/7.htm) 后遇到了这个想法,但该网站没有一个可行的示例,无论我尝试了多少,我都无法让它发挥作用。我不断收到“无法实例化抽象类”,因为未实现纯虚函数 get_Site 和 put_Site(根据第二个 sn-p)。

编辑 请注意,我使用的是 VS2010。下面的示例实现:

class ATL_NO_VTABLE CArticle :
    public CComObjectRootEx<CComSingleThreadModel>,
    public CComCoClass<CArticle, &CLSID_Article>,
    public IDispatchImpl<IArticle, &IID_IArticle, &LIBID_GeodeEdiLib, /*wMajor =*/ 1, /*wMinor =*/ 0>
{
public:
    CArticle()
    {
    }

【问题讨论】:

  • 哪个类是抽象的,不能实例化?
  • SharedProperties::get_SiteSharedProperties::put_Site 不应该是虚拟的吗?
  • 它们是,但如果您熟悉 ATL,我相信您会明白这一点。 sn-p 不是实际的源代码。它仅用于说明目的。
  • 不行,您需要定义所有这些类都实现的 IShared 接口。缺点是客户端代码必须对其进行 QI,就像聚合一样。您必须在每个中编写 Site 方法,您可以委托给一个通用实现。

标签: templates visual-c++ inheritance com atl


【解决方案1】:

编译器不知道get_Siteput_Site 方法实现了接口中的方法。您需要从相应的接口继承 SharedProperties 类模板。这就是让SharedProperties 成为模板的理由。

interface IA
{
    STDMETHOD(get_Site)() = 0;
    STDMETHOD(put_Site)() = 0;
};

template<typename T>
class Sharedproperties : T
{
public:
    STDMETHODIMP get_Site() { return E_NOTIMPL; };
    STDMETHODIMP put_Site() { return E_NOTIMPL; };
};

class CAX : public IA
{
    STDMETHOD(other)() { return S_OK; }
}

class CA: public Sharedproperties<CAX>
{
public:
    CA() {}
};

请注意,CA 类并非直接继承自接口 IA。

编辑: VS2008 类向导为一个简单的 ATL 类对象生成此继承:

class ATL_NO_VTABLE CMyObject :
    public CComObjectRootEx<CComMultiThreadModel>,
    public CComCoClass<CMyObject, &CLSID_MyObject>,
    IMyObject

其中IMyObject 是IDL 定义的接口中的。所以在 ATL 上下文中你只需要替换 IMyObject 继承:

class ATL_NO_VTABLE CMyObject :
    public CComObjectRootEx<CComMultiThreadModel>,
    public CComCoClass<CMyObject, &CLSID_MyObject>,
    public Sharedproperties<MyIntermediateClass>

【讨论】:

  • 您在继承层次结构中放置了一个中间类。这是一个简洁的解决方案,但它不适用于 ATL 的上下文,因为 CA 类不直接从 IA 继承。
  • 在这种情况下,类模板必须继承自中间类。我已经编辑了示例代码来说明这种情况。
  • 这很奇怪,但您的解决方案确实有意义。 VS2010生成的代码请参考我编辑的帖子。
猜你喜欢
  • 2013-09-19
  • 2012-03-03
  • 2015-04-23
  • 2012-10-05
  • 2011-06-10
  • 2010-12-03
  • 2011-07-12
  • 2012-08-04
  • 2011-01-12
相关资源
最近更新 更多