Один из выводов, который можно сделать из трех требований
Из того, что все объекты СОМ имеют статическую иерархию типов, следует, что утверждение, записанное в следующем коде, никогда не должно быть ложным, несмотря на то, что идентификатор интерфейса используется в качестве второго параметра:
void AssertStaticType(IUnknown *pUnk, REFIID riid)
{
IUnknown *pUnk1 = 0,
*pUnk2 = 0;
HRESULT hr1 = pUnk->QueryInterface(riid, (void**)&pUnk1);
HRESULT hr2 = pUnk->QueryInterface(riid, (void**)&pUnk2);
// both requests for the same interface should
// yield the same yes/no answer
// оба запроса того же самого интерфейса
// должны получить тот же самый ответ да/нет
assert(SUCCEEDED(hr1) == SUCCEEDED(hr2));
if (SUCCEEDED(hr1)) pUnk1->Release();
if (SUCCEEDED(hr2)) pUnk2->Release();
}
Это требование означает, что в СОМ запрещены следующие программные технологии:
Использование временной информации при решении вопроса о том, удовлетворять или нет запрос
Использование переменной информации о состоянии при решении вопроса о том, удовлетворять или нет запрос
Использование маркера доступа (
Использование успешного захвата динамических ресурсов для решения вопроса о том, удовлетворять или нет запрос
Эта последняя методика может быть до некоторой степени смягчена, если разработчик объекта желает поупражняться с выражением спецификации СОМ «barring catastrophic failure» (за исключением катастрофического сбоя).
Эти ограничения не означают, что два объекта одного и того же класса реализации не могут давать различные ответы «да/нет» при запросе одного и того же интерфейса. Например, класс может реализовать показанные ранее интерфейсы
class СВР : public ICar, public IPlane, public IBoat
{
enum TYPE { CAR, BOAT, PLANE, NONE };
TYPE m_type;
CBP(void) : m_type(NONE) { }
STDMETHODIMP QueryInterface(REFIID riid, void **ppv)
{
if (md == IID_ICar)
{
// 1st QI Initializes type of object
// первая QI инициализирует тип объекта
if (m_type == NONE) m_type = CAR;
// only satisfy request if this object is a car
// удовлетворяем запрос, только если данный объект
// является car (автомобилем)
if (m_type == CAR) *ppv = static_cast
else return (*ppv = 0), E_NOINTERFACE;
}
else if (md == IID_IBoat)
{
// similar treatment for IBoat and IPlane
// IBoat и IPlane обрабатываются сходным образом
}
};