【发布时间】:2016-05-08 20:40:30
【问题描述】:
我有一个使用 ATL 实现的 COM 对象 CProvider。此类包含另一个类 CProviderInfo,并维护此内部类类型的对象的静态向量。
它是这样的:
//-------------
// CProvider.h
//-------------
//
// COM object class
//
class ATL_NO_VTABLE CProvider :
public CComObjectRootEx<CComMultiThreadModel>,
public CComCoClass<CProvider, &CLSID_Provider>,
public Interface1,
public Interface2
{
public:
BEGIN_COM_MAP(CProvider)
COM_INTERFACE_ENTRY(Interface1)
COM_INTERFACE_ENTRY(Interface2)
END_COM_MAP()
//
// The inner class
//
class CProviderInfo
{
public:
CProviderInfo();
CComBSTR m_strName;
GUID m_guidRegistration;
};
private:
//
// static vector of inner class type
//
static vector<CProviderInfo> m_vProviderInfo;
};
我想做的是在 CProvider 上引入一个方法,该方法返回静态向量 m_vProviderInfo 的副本。尝试按 COM 规则玩,为此我引入了一个新的 IDL 接口 IProviderInfoRetriever:
//---------
// IDL file
//---------
//
// IProviderInfoRetriever interface
//
[
// uuid, version ... etc.
]
interface IProviderInfoRetriever : IUnknown
{
HRESULT GetProviderInfo(
[out, retval] SAFEARRAY(IProviderInfo*) *ppProviderInfo);
}
//
// The interface of the class holding the info
//
[
// uuid, version ... etc.
]
interface IProviderInfo : IUnknown
{
[propget]
HRESULT Name(
[out, retval] BSTR *pbstrName);
[propget]
HRESULT Registration(
[out, retval] GUID *pguidRegistration);
}
我的计划是让 CProvider 实现 IProviderInfoRetriever 有效地将静态向量 m_vProviderInfo 的内容复制到 IProviderInfoRetriever 的输出 SAFEARRAY 中::GetProviderInfo().
我的问题是:是否可以让内部类 CProviderInfo 实现 IProviderInfo?这会破坏创建 CProviderInfo 类型的局部变量的现有代码吗?
【问题讨论】:
-
如果不是“实现一个或多个 COM 接口的类”,“COM 类”是什么意思?不,没有什么能阻止你在堆栈上创建一个
CProvider的实例(CProvider显然是一个“COM 类”,无论你想到什么定义)。 -
另一种选择,如果触摸
CProviderInfo与您有关,将是编写一个实现IProviderInfo并将CProviderInfo作为成员的包装类(或者甚至只是一个指向元素的指针,或原始向量的索引)。这将很好地隔离与 COM 相关的部分,并最大限度地减少对代码库其余部分的占用。 -
@IgorTandetnik 我也是这么想的。经过一番研究,我发现继承 IUnknown 会破坏现有代码,因为它会将 CProviderInfo 变成一个抽象类。不可能实例化 CProviderInfo,除非通过 CComObject、CComObjectStack 和这个类家族,因为它提供了 IUnknown 成员的实现。
-
是的,抱歉,我忘记了 ATL 的
IUnknown的两阶段实现。那么,包装器方法看起来更有吸引力。 -
不用担心。复杂的 COM 之上的 ATL 细节简直是不人道的。