Сущность технологии COM



Множественные интерфейсы и имена методов - часть 4


Использование вложенных классов не является обязательным, но оно подчеркивает, что эти подчиненные классы не имеют смысла вне контекста класса CarPlane. Рисунок 4.7 показывает двоичное размещение этого класса и размещения соответствующих vtbl.

Рис. 4.7. Реализация, основанная на композиции

Отметим, что имеется два определения вложенного класса, по одному для каждого реализованного им интерфейса. Это позволяет разработчику объекта обеспечить две различных реализации GetMaxSpeed:

STDMETHODIMP CarPlane::XCar::GetMaxSpeed(long *pn) { // set *pn to max speed for cars // устанавливаем *pn для максимальной скорости автомобилей }

STDMETHODIMP CarPlane::XPlane::GetMaxSpeed(long *pn) { // set *pn to max speed for planes // устанавливаем *pn для максимальной скорости самолетов }

Тот факт, что две реализации GetMaxSpeed встречаются в различных определениях вложенных классов, позволяет определить метод дважды и к тому же гарантирует то, что таблицы vtbl, соответствующие ICar и IPlane, будут иметь различные элементы для GetMaxSpeed.

Необходимо также отметить, что хотя класс CarPlane, находящийся на верхнем уровне, реализует методы IUnknown, он не наследует никакому производному от IUnknown классу. Вместо этого объекты CarPlane имеют элементы данных, которые наследуют интерфейсам СОМ. Это значит, что вместо того, чтобы использовать static_cast для вхождения в объект и нахождения определенного указателя vptr, реализация QueryInterface в CarPlane должна возвратить указатель на тот элемент данных, который реализует запрашиваемый интерфейс:

STDMETHODIMP CarPlane::QueryInterface(REFIID riid, void **ppv) { if (riid == IID_IUnknown) *ppv = static_cast<IUnknown*>(&m_xCar); else if (riid == IID_IVehicle) *ppv = static_cast<IVehicle*> (&m_xCar); else if (riid == IID_ICar) *ppv = static_cast<ICar*>(&m_xCar); else if (riid == IID_IPlane) *ppv = static_cast<IPlane*>(&m_xPlane); else return (*ppv = 0), E_NOINTERFACE;

((IUnknown*)(*ppv))->AddRef(); return S_OK; }




Содержание  Назад  Вперед