Чтение онлайн

на главную - закладки

Жанры

Сущность технологии СОМ. Библиотека программиста
Шрифт:

Для полного охвата проблем, относящихся к унифицированию идентификации через границы компонентов, рассмотрим следующую простую реализацию ICar:

class Car : public ICar

{

LONG m_cRef; Car(void) : m_cRef(0) {} STDMETHODIMP QueryInterface(REFIID, void **);

STDMETHODIMP_(ULONG) AddRef(void); STDMETHODIMP_(ULONG) Release(void);

STDMETHODIMP GetMaxSpeed(long *pn);

STDMETHODIMP Brake(void); };

STDMETHODIMP Car::QueryInterface(REFIID riid, void **ppv)

{

if (riid == IID_IUnknown) *ppv = static_cast<IUnknown*>(this);

else if (riid == IID_IVehicle) *ppv = static_cast<IVehicle*>(this);

else if (riid == IID_ICar) *ppv = static_cast<ICar*>(this);

else return (*ppv = 0), E_NOINTERFACE;

((IUnknown*)*ppv)->AddRef;

return S_OK;

}

// car class object's IClassFactory::CreateInstance

//

интерфейс IClassFactory::CreateInstance

// объекта класса car

STDMETHODIMP CarClass::CreateInstance(IUnknown *pUnkOuter, REFIID riid, void **ppv)

{

Car *pCar = new Car;

if (*pCar) return (*ppv = 0), E_OUTOFMEMORY;

pCar->AddRef;

HRESULT hr = pCar->QueryInterface(riid, ppv);

pCar->Release; return hr;

}

Этот класс просто использует фактические реализации QueryInterface, AddRef и Release.

Рассмотрим второй класс C++, который пытается использовать реализацию Car как двоичный композит:

class CarBoat : public IBoat

{

LONG m_cRef;

Unknown *m_pUnkCar;

CarBoat(void);

virtual ~CarBoat(void);

STDMETHODIMP QueryInterface(REFIID, void **);

STDMETHODIMP_(ULONG) AddRef(void);

STDMETHODIMP_(ULONG) Release(void);

STDMETHODIMP GetMaxSpeed(long *pn);

STDMETHODIMP Sink(void);

};

Для эмуляции композиции разработчику пришлось бы создать подобъект Car, а деструктору – освободить указатель на подобъект:

CarBoat::CarBoat (void) : m_cRef(0)

{

HRESULT hr = CoCreateInstance(CLSID_Car, 0, CLSCTX_ALL, IID_IUnknown, (void**)&m_pUnkCar);

assert(SUCCEEDED(hr));

}

CarBoat::~CarBoat(void)

{

if (m_pUnkCar) m_pUnkCar->Release;

}

Интересная проблема возникает в реализации QueryInterface:

STDMETHODIMP CarBoat::QueryInterface(REFIID riid, void **ppv)

{

if (riid == IID_IUnknown) *ppv = static_cast<IUnknown*>(this);

else if (riid == IID_IVehicle) *ppv = static_cast<IVehicle*>(this);

else if (riid == IID_IBoat) *ppv = static_cast<IBoat*>(this);

else if (riid == IID_ICar)

// forward request…

// переадресовываем запрос…

return m_pUnkCar->QueryInterface(riid, ppv);

else return (*ppv = 0), E_NOINTERFACE; ((IUnknown*)*ppv)->AddRef;

return S_OK;

}

Поскольку объект Car не имеет понятия о том, что он является частью идентификационной единицы (identity) другого объекта, то он будет причиной

неуспеха любых запросов QueryInterface для IBoat. Это означает, что

QI(IBoat)->ICar

пройдет успешно, а запрос

QI(QI(IBoat)->ICar)->IBoat

потерпит неудачу, так как полученная QueryInterface будет несимметричной. Вдобавок запросы QueryInterface о IUnknown через интерфейсные указатели ICar и IBoat вернут различные значения, а это означает, что будет идентифицировано два различных объекта. Из подобных нарушений протокола IUnknown следует, что объекты CarBoat попросту не являются действительными объектами СОМ.

Идея составления объекта из двоичных композитов звучит красиво. Действительно, Спецификация СОМ четко и подробно указывает, как реализовать эту идею в стандартной и предсказуемой манере. Технология выставления клиенту двоичного подкомпонента непосредственно через QueryInterface называется СОМ-агрегированием. СОМ-агрегирование является лишь набором правил, определяющих отношения между внешним объектом (агрегирующим) и внутренним (агрегируемым). СОМ-агрегирование – это просто набор правил IUnknown, позволяющих более чем одному двоичному компоненту фигурировать в качестве идентификационной единицы (identity) СОМ.

Агрегирование СОМ несомненно является главной движущей силой для повторного использования в СОМ. Намного проще приписывать объекту значения и использовать его методы в реализации методов других объектов. Только в редких случаях кто-то захочет выставлять интерфейсы другого объекта непосредственно клиенту как часть той же самой идентификационной единицы. Рассмотрим следующий сценарий:

class Handlebar : public IHandlebar { … };

class Wheel : public IWheel {};

class Bicycle : public IBicycle

{

IHandlebar * m_pHandlebar;

IWheel *m_pFrontWheel;

IWheel *m_pBackWheel;

}

Было бы опрометчиво для класса Вicycle объявлять интерфейсы IHandlebar (велосипедный руль) или IWheel (колесо) в собственном методе QueryInterface. QueryInterface зарезервирован для выражения отношений «является» (is-a), а велосипед (bicycle) очевидно не является колесом (wheel) или рулем (handlebar). Если разработчик Bicycle хотел бы обеспечить прямой доступ к этим сторонам объекта, то интерфейс IBicycle должен был бы иметь для этой цели аксессоры определенных свойств:

Поделиться:
Популярные книги

Родословная. Том 2

Ткачев Андрей Юрьевич
2. Линия крови
Фантастика:
городское фэнтези
аниме
фэнтези
5.00
рейтинг книги
Родословная. Том 2

Волхв

Земляной Андрей Борисович
3. Волшебник
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Волхв

Возвышение Меркурия. Книга 4

Кронос Александр
4. Меркурий
Фантастика:
героическая фантастика
боевая фантастика
попаданцы
5.00
рейтинг книги
Возвышение Меркурия. Книга 4

Отморозок 4

Поповский Андрей Владимирович
4. Отморозок
Фантастика:
попаданцы
фантастика: прочее
5.00
рейтинг книги
Отморозок 4

Газлайтер. Том 14

Володин Григорий Григорьевич
14. История Телепата
Фантастика:
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Газлайтер. Том 14

АллатРа

Новых Анастасия
Научно-образовательная:
психология
история
философия
обществознание
физика
6.25
рейтинг книги
АллатРа

Золотой ворон

Сакавич Нора
5. Все ради игры
Фантастика:
зарубежная фантастика
5.00
рейтинг книги
Золотой ворон

Курсант: Назад в СССР 4

Дамиров Рафаэль
4. Курсант
Фантастика:
попаданцы
альтернативная история
7.76
рейтинг книги
Курсант: Назад в СССР 4

Все ведьмы – стервы, или Ректору больше (не) наливать

Цвик Катерина Александровна
1. Все ведьмы - стервы
Фантастика:
юмористическая фантастика
5.00
рейтинг книги
Все ведьмы – стервы, или Ректору больше (не) наливать

Мужчина моей судьбы

Ардова Алиса
2. Мужчина не моей мечты
Любовные романы:
любовно-фантастические романы
8.03
рейтинг книги
Мужчина моей судьбы

Случайная жена для лорда Дракона

Волконская Оксана
Фантастика:
юмористическая фантастика
попаданцы
5.00
рейтинг книги
Случайная жена для лорда Дракона

Кровь на клинке

Трофимов Ерофей
3. Шатун
Фантастика:
боевая фантастика
попаданцы
альтернативная история
6.40
рейтинг книги
Кровь на клинке

Барон устанавливает правила

Ренгач Евгений
6. Закон сильного
Старинная литература:
прочая старинная литература
5.00
рейтинг книги
Барон устанавливает правила

Кротовский, вы сдурели

Парсиев Дмитрий
4. РОС: Изнанка Империи
Фантастика:
попаданцы
альтернативная история
рпг
5.00
рейтинг книги
Кротовский, вы сдурели