void AssertSymmetric(ICar *pCar) { if (pCar)

{

IPlane *pPlane = 0;

// request a second type of interface

// запрашиваем второй тип интерфейса

HRESULT hr = pCar->QueryInterface(IID_IPlane, (void**)&pPlane);

if (SUCCEEDED(hr)) { ICar *pCar2 = 0;

// request original type of interface

// запрашиваем исходный тип интерфейса

hr = pPlane->QueryInterface(IID_ICar, (void**)&pCar2);

// if the following assertion fails, pCar

// did not point to a valid СОМ object

// если следующее утверждение не будет правильным,

// то pCar не укажет на правильный СОМ-объект

assert(SUCCEEDED(hr));

pCar2->Release();

}

pPlane->Release();

}

}

Симметричность QueryInterface означает, что клиенты не должны заботиться о том, какой из интерфейсов запрашивать первым, так как любые два типа интерфейсов могут быть запрошены в любом порядке.

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 был и рефлективным.

QueryInterface рефлективна

Спецификация СОМ требует, чтобы запрос QueryInterface через интерфейсный указатель всегда достигал цели, если запрошенный тип соответствует типу указателя, с помощью которого произведен запрос. Это означает, что QI(A)->A всегда должен быть верным.

Это требование проиллюстрировано рис. 4.4 и в следующем фрагменте кода:

Добавить отзыв
ВСЕ ОТЗЫВЫ О КНИГЕ В ИЗБРАННОЕ

0

Вы можете отметить интересные вам фрагменты текста, которые будут доступны по уникальной ссылке в адресной строке браузера.

Отметить Добавить цитату