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



Обобщения - часть 3


Этот код является семантически идентичным варианту с функцией, которая использовала интерфейс IApeClass вместо интерфейса IClassFactory.

Для того чтобы предыдущий пример работал корректно, объекту класса Gorilla следует реализовать IClassFactory:

class GorillaClass : public IClassFactory { public: IMPLEMENT_UNKNOWN_NO_DELETE(GorillaClass) BEGIN_INTERFACE_TABLE(GorillaClass) IMPLEMENTS_INTERFACE(IClassFactory) END_INTERFACE_TABLE() STDMETHODIMP CreateInstance(IUnknown *pUnkOuter, REFIID riid, void **ppv) { *ppv = 0; if (pUnkOuter != 0) // we don't support aggregation yet // мы еще не поддерживаем агрегирование return CLASS_E_NOAGGREGATION; // create a new instance of our C++ class Gorilla // создаем новый экземпляр нашего С++-класса Gorilla Gorilla *p = new Gorilla; if (p == 0) return E_OUTOFMEMORY: // increment reference count by one // увеличиваем счетчик ссылок на единицу p->AddRef(); // store the resultant interface pointer into *ppv // записываем результирующий указатель интерфейса в *ppv HRESULT hr = p->QueryInterface(riid, ppv); // decrement reference count by one, which will delete the // object if QI fails // уменьшаем на единицу счетчик ссылок, // что уничтожит объект при отказе QI p->Release(); // return result of Gorilla::QueryInterface // возвращаем результат работы Gorilla::QueryInterface return hr; }

STDMETHODIMP LockServer(BOOL bLock); };

Реализация LockServer будет обсуждаться в этой главе позже. Отметим, что реализация CreateInstance, в первую очередь, создает новый объект C++ на базе класса Gorilla и запрашивает объект, поддерживает ли он нужный интерфейс. Если объект поддерживает требуемый интерфейс, то вызов QueryInterface инициирует вызов AddRef, и клиент в конечном счете выполнит соответствующий вызов Release. Если же произойдет отказ QueryInterface, то потребуется некоторый механизм для уничтожения созданного нового объекта. Предыдущий пример использует стандартную технологию "заключения в скобки" (bracketing) вызова QueryInterface между парой AddRef/Release.Если произошел сбой вызова QueryInterface, то вызов Release сбросит счетчик ссылок на нуль, запуская тем самым удаление объекта. Если же вызов QueryInterface прошел успешно, то вызов Release установит счетчик ссылок на единицу. Остающаяся ссылка принадлежит клиенту, который и выполнит последний вызов Release, когда объект более не нужен.




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