我有一个COM对象, CProvider ,使用ATL实现。此类包含另一个类 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 ?
类型的局部变量的现有代码答案 0 :(得分:1)
我做了一些广泛的研究,答案很简单:是的,但这并不容易。您不太可能只是拥有一个普通的C ++类继承/实现IDL中定义的接口,而不会破坏依赖于所述C ++类的现有代码。
首先,如果你使用ATL的工具将你的C ++类转换为COM类,你会突然发现这个C ++类由于ATL宏引入的所有纯虚函数而变得抽象。因此,至少,您将IUnknown
AddRef()
,Release()
和QueryInterface()
由ATL宏添加到您的C ++类中虚函数,例如
class ATL_NO_VTABLE CProviderInfo:
public CComObjectRootEx<CComMultiThreadModel>,
public IProviderInfo
{
public:
BEGIN_COM_MAP(CProviderInfo)
COM_INTERFACE_ENTRY(IProviderInfo)
END_COM_MAP() // This line adds IUnknown's AddRef(), Release(),
// and QueryInterface() as pure virtual functions.
// ...
};
仅此一项就会破坏用于创建C ++类实例的任何现有代码,无论是堆栈还是堆(使用new运算符)。所以,最后你有两个选择:
使用ATL的工具将您的C ++类转换为COM类。
这会将您的C ++类变成抽象类。您必须修改源代码中创建C ++类对象的所有位置,以使用ATL的类,即CComObject
,CComObjectStack
等等。
直接和手动继承/实现IDL中定义的接口。
这将需要提供您自己的IUnknown
,IDispatch
或两者的实现,具体取决于您的接口,以及您的接口本身定义的任何方法的实现。此选项的优点是不太可能破坏代码库中C ++类的任何现有用法。
然而,在没有ATL的情况下滚动自己的COM接口实现并不总是那么容易,特别是如果您的C ++类涉及复杂的场景,例如互操作。