如何使 ATL COM 类从基类派生?

发布于 2024-07-08 08:27:58 字数 1677 浏览 10 评论 0原文

“ATL 简单对象”向导不提供指定新类派生自现有组件类及其接口的方法。 在 Visual Studio 2008 中,如何创建一个从现有 ATL COM 类派生的新 ATL COM 类(即 Base 实现 IBase,并且我想创建一个新的 Derived 类派生自实现 IDerivedBase,其中 IDerived 派生自 IBase。)

更新:听起来很简单,但是向导生成的 ATL 类最多有六个基类、一个 COM 映射和一个连接点映射。 这些基类和映射中的哪一个应该在派生类中重复? 如果映射在派生类中重复,它们应该包含基类映射的内容还是仅包含附加项? 基类的顺序重要吗? FinalConstruct()FinalRelease() 怎么样? DECLARE_PROTECT_FINAL_CONSTRUCTDECLARE_REGISTRY_RESOURCEID 是否应该在派生类中重复?

这是一个示例基类,除了所有样板之外,它是空的。 现在派生类应该是什么样子?

class ATL_NO_VTABLE CBase :
    public CComObjectRootEx<CComSingleThreadModel>,
    public CComCoClass<CBase, &CLSID_Base>,
    public ISupportErrorInfo,
    public IConnectionPointContainerImpl<CBase>,
    public CProxy_IBaseEvents<CBase>,
    public IDispatchImpl<IBase, &IID_IBase, &LIBID_ExampleLib, /*wMajor =*/ 1, /*wMinor =*/ 0>
{
public:
    CBase()
    {
    }

DECLARE_REGISTRY_RESOURCEID(IDR_Base)


BEGIN_COM_MAP(CBase)
    COM_INTERFACE_ENTRY(IBase)
    COM_INTERFACE_ENTRY(IDispatch)
    COM_INTERFACE_ENTRY(ISupportErrorInfo)
    COM_INTERFACE_ENTRY(IConnectionPointContainer)
END_COM_MAP()

BEGIN_CONNECTION_POINT_MAP(CBase)
    CONNECTION_POINT_ENTRY(__uuidof(_IBaseEvents))
END_CONNECTION_POINT_MAP()
// ISupportsErrorInfo
    STDMETHOD(InterfaceSupportsErrorInfo)(REFIID riid);


    DECLARE_PROTECT_FINAL_CONSTRUCT()

    HRESULT FinalConstruct()
    {
        return S_OK;
    }

    void FinalRelease()
    {
    }
};

OBJECT_ENTRY_AUTO(__uuidof(Base), CBase)

The "ATL simple object" wizard doesn't provide a way to specify that a new class is derived from an existing coclass and its interface. In Visual Studio 2008, how do I make a new ATL COM class derived from an existing one (i.e. Base implements IBase, and I want to make a new Derived class derived from Base that implements IDerived, where IDerived is derived from IBase.)

Update: it sounds simple, but a wizard-generated ATL class has up to six base classes, a COM map and a connection point map. Which of these base classes and maps should be repeated in the derived class? If maps are repeated in the derived class should they contain the contents of the base class map or just the additional items? Does the order of base classes matter? What about FinalConstruct() and FinalRelease()? Should DECLARE_PROTECT_FINAL_CONSTRUCT and DECLARE_REGISTRY_RESOURCEID be repeated in the derived class?

Here's a sample base class that is empty except for all the boilerplate. Now what should the derived class look like?

class ATL_NO_VTABLE CBase :
    public CComObjectRootEx<CComSingleThreadModel>,
    public CComCoClass<CBase, &CLSID_Base>,
    public ISupportErrorInfo,
    public IConnectionPointContainerImpl<CBase>,
    public CProxy_IBaseEvents<CBase>,
    public IDispatchImpl<IBase, &IID_IBase, &LIBID_ExampleLib, /*wMajor =*/ 1, /*wMinor =*/ 0>
{
public:
    CBase()
    {
    }

DECLARE_REGISTRY_RESOURCEID(IDR_Base)


BEGIN_COM_MAP(CBase)
    COM_INTERFACE_ENTRY(IBase)
    COM_INTERFACE_ENTRY(IDispatch)
    COM_INTERFACE_ENTRY(ISupportErrorInfo)
    COM_INTERFACE_ENTRY(IConnectionPointContainer)
END_COM_MAP()

BEGIN_CONNECTION_POINT_MAP(CBase)
    CONNECTION_POINT_ENTRY(__uuidof(_IBaseEvents))
END_CONNECTION_POINT_MAP()
// ISupportsErrorInfo
    STDMETHOD(InterfaceSupportsErrorInfo)(REFIID riid);


    DECLARE_PROTECT_FINAL_CONSTRUCT()

    HRESULT FinalConstruct()
    {
        return S_OK;
    }

    void FinalRelease()
    {
    }
};

OBJECT_ENTRY_AUTO(__uuidof(Base), CBase)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

萌梦深 2024-07-15 08:27:58

只是一个建议 - 如果您的 COM 对象不需要对 COM 相关的东西做任何特殊的事情,那么您可以实现代码,以便将您的 COM 基类所做的实际逻辑封装在另一个普通的旧 C++ 类(例如 CBaseLogic)中。

CBaseLogic : IBase

class ATL_NO_VTABLE CBase :
    public CComObjectRootEx<CComSingleThreadModel>,
    public CComCoClass<CBase, &CLSID_Base>,
    public ISupportErrorInfo,
    public IConnectionPointContainerImpl<CBase>,
    public CProxy_IBaseEvents<CBase>,
    public IDispatchImpl<IBase, &IID_IBase, &LIBID_ExampleLib
{
CBaseLogic m_LogicObj; /* Method calls are simply forwarded to this member */
};


CDerivedLogic : public CBaseLogic

class ATL_NO_VTABLE CDerived :
    public CComObjectRootEx<CComSingleThreadModel>,
    public CComCoClass<CDerived, &CLSID_Base>,
    public ISupportErrorInfo,
    public IConnectionPointContainerImpl<CDerived>,
    public CProxy_IBaseEvents<CDerived>,
    public IDispatchImpl<IBase, &IID_IBase, &LIBID_ExampleLib
{
CDerivedLogic m_LogicObj;
};

这可以实现您想要做的事情,并具有以下附加优势:

  1. 使您的真实程序逻辑与基础设施/包装(COM)分离,
  2. 使真实逻辑平台独立。
  3. 未来的维护者不需要理解你聪明的 COM hack
  4. 保持你的程序逻辑干净,远离 COM 语法,提高可读性
  5. 使得在其他形式的封装中重用真实逻辑,例如作为 C DLL

Just a suggestion - if your COM object does not need to do anything special with COM related stuff then you can implement code such that the real logic that your base COM class does is encapsulated in another plain old C++ class say CBaseLogic.

CBaseLogic : IBase

class ATL_NO_VTABLE CBase :
    public CComObjectRootEx<CComSingleThreadModel>,
    public CComCoClass<CBase, &CLSID_Base>,
    public ISupportErrorInfo,
    public IConnectionPointContainerImpl<CBase>,
    public CProxy_IBaseEvents<CBase>,
    public IDispatchImpl<IBase, &IID_IBase, &LIBID_ExampleLib
{
CBaseLogic m_LogicObj; /* Method calls are simply forwarded to this member */
};


CDerivedLogic : public CBaseLogic

class ATL_NO_VTABLE CDerived :
    public CComObjectRootEx<CComSingleThreadModel>,
    public CComCoClass<CDerived, &CLSID_Base>,
    public ISupportErrorInfo,
    public IConnectionPointContainerImpl<CDerived>,
    public CProxy_IBaseEvents<CDerived>,
    public IDispatchImpl<IBase, &IID_IBase, &LIBID_ExampleLib
{
CDerivedLogic m_LogicObj;
};

This achieves what you are trying to do with the added advantage of

  1. Keeps your real program logic separate from the infrastructure / packaging (COM)
  2. Makes the real logic platform independent.
  3. Future maintainer need not understand your clever COM hack
  4. Keeps your program logic clean and away from the COM syntax, improving readability
  5. Makes re-use of real logic easier in other forms of packaging eg as a C DLL
<逆流佳人身旁 2024-07-15 08:27:58

编辑向导生成的代码。 如果您希望从其他接口派生对象,请将这些基类添加到生成的类声明中。

Edit the code that the wizards generate. If you want an object to derive from additional interfaces, add these base classes to the resulting class declaration.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文