Как сделать класс ATL COM производным от базового класса? - PullRequest
9 голосов
/ 17 ноября 2008

Мастер «Простой объект ATL» не позволяет указать, что новый класс является производным от существующего кокласса и его интерфейса. В Visual Studio 2008 как создать новый класс COM ATL, производный от существующего (т. Е. Base реализует IBase, и я хочу создать новый класс Derived, производный от Base, реализующий IDerived где IDerived является производным от IBase.)

Обновление: звучит просто, но сгенерированный мастером класс ATL имеет до шести базовых классов, карту COM и карту точки подключения. Какие из этих базовых классов и карт должны быть повторены в производном классе? Если карты повторяются в производном классе, должны ли они содержать содержимое карты базового класса или только дополнительные элементы? Имеет ли значение порядок базовых классов? А как насчет FinalConstruct() и FinalRelease()? Должны ли DECLARE_PROTECT_FINAL_CONSTRUCT и DECLARE_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)

Ответы [ 2 ]

1 голос
/ 17 декабря 2008

Просто предложение - если вашему 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 *
  4. Содержит логику вашей программы в чистоте и вне синтаксиса COM, улучшая читабельность
  5. Упрощает повторное использование реальной логики в других формах упаковки, например, в виде C DLL
0 голосов
/ 18 ноября 2008

Редактировать код, который генерируют мастера. Если вы хотите, чтобы объект был производным от дополнительных интерфейсов, добавьте эти базовые классы в объявление результирующего класса.

...