Как сделать класс 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;
};
Это позволяет добиться того, что вы пытаетесь сделать, с дополнительным преимуществом
- Сохраняет вашу реальную логику программы отдельно от инфраструктуры / упаковки (COM)
- Делает настоящую логическую платформу независимой.
- Будущий сопровождающий не должен понимать ваш умный взлом COM
- Содержит логику вашей программы в чистоте и вдали от синтаксиса COM, улучшая читабельность
- Облегчает повторное использование реальной логики в других формах упаковки, например, как C DLL
Отредактируйте код, который генерируют мастера. Если вы хотите, чтобы объект был производным от дополнительных интерфейсов, добавьте эти базовые классы в результирующее объявление класса.