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

2bbc099f

QueryInterface транзитивна


Спецификация СОМ требует также, чтобы, если запрос QueryInterface на интерфейс В удовлетворяется через интерфейсный указатель типа A, а второй запрос QueryInterface на интерфейс C удовлетворяется через указатель типа В, то запрос QueryInterface на интерфейс C через исходный указатель типа A был бы также успешным. Это означает, что если верно

QI(QI(A)->B)->C

то должно быть верным и

QI(A)->C

Это условие иллюстрируется рис. 4.3 и означает, что утверждение, приведенное в нижеследующем коде, должно всегда быть верным:

void AssertTransitive(ICar *pCar) { if (pCar) { IPlane *pPlane = 0; // request intermediate type of interface // запрос промежуточного типа интерфейса HRESULT hr = pCar->QueryInterface(IID_IPlane, (void**)&pPlane); if (SUCCEEDED(hr)) { IBoat *pBoat1 = 0; // request terminal type of interface // запрос конечного типа интерфейса hr = pPlane->QueryInterface(IID_IBoat, (void**)&pBoat1); if (SUCCEEDED(hr)) { IBoat *pBoat2 = 0; // request terminal type through the original pointer // запрос конечного типа через исходный указатель hr = pCar->QueryInterface(IID_IBoat, (void**)&pBoat2); // if the following assertion fails, pCar // did not point to a valid СОМ object // если следующее утверждение неверно, то pCar // не указывал на корректный СОМ-объект assert(SUCCEEDED(hr)); pBoat2->Release(); } pBoat1->Release(); } pPlane->Release(); } }

Из транзитивности QueryInterface следует, что все интерфейсы, которые выставляет объект, равноправны и не требуют, чтобы их вызывали в какой-то определенной последовательности. Если бы это было не так, то клиентам пришлось бы заботиться о том, какой указатель на объект использовать для различных запросов QueryInterface. Из транзитивности и симметричности QueryInterface следует, что любой интерфейсный указатель на объект выдаст тот же самый ответ "да/нет" на любой запрос QueryInterface. Единственная ситуация, не охватываемая транзитивностью и симметричностью, это повторные запросы одного и того же интерфейса. Эта ситуация требует, чтобы QueryInterface был и рефлективным.



Содержание раздела