Как сделать класс ATL COM производным от базового класса?

Мастер "Простой объект 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 ответа

Просто предложение - если вашему 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

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

Другие вопросы по тегам