Итак, настало время разобраться, как должны быть организованы классы для реализации интерфейсов типа IUnknown и IClassFactory. Вот. Первое, мы должны завести класс наследуемый интерфейс IUnkonwn. Вот например так.
class IMath : public IUnknown { public: STDMETHOD(Add) ( long, long, long* ) PURE; STDMETHOD(Subtract) ( long, long, long* ) PURE; STDMETHOD(Multiply) ( long, long, long* ) PURE; STDMETHOD(Divide) ( long, long, long* ) PURE; };
Отдельно можно объвить класс со специальными функциями.
class IAdvancedMath : public IUnknown { public: STDMETHOD(Factorial)( short, long* ) PURE; STDMETHOD(Fibonacci)( short, long* ) PURE; };
Вот теперь унаследуем эти классы в новый класс и реализуем методы от наследуемых классов.
class Math : public IMath, public IAdvancedMath { ........ };
Кроме этого нам необходим класс фабрики классов IClassFactory, объявить его можно примерно так.
class MathClassFactory : public IClassFactory { protected: long m_lRef; public: MathClassFactory(); ~MathClassFactory(); // IUnknown STDMETHOD( QueryInterface(REFIID, void** )); STDMETHOD_(ULONG, AddRef()); STDMETHOD_(ULONG, Release()); // IClassFactory STDMETHOD(CreateInstance)(LPUNKNOWN, REFIID, void**); STDMETHOD(LockServer)(BOOL); };
Как видите, что здесь даже нет упоминания о классах объявленных ранее. Но это упоминание есть в методе CreateInstance
STDMETHODIMP MathClassFactory::CreateInstance ( LPUNKNOWN pUnkOuter, REFIID riid, void** ppvObj ) { Math* pMath; HRESULT hr; *ppvObj = 0; pMath = new Math; .............. }
Лично я, например, потратил довольно много времени, чтобы осознать, что интерфейс IUnknown наследуется, а IClassFactory как бы в стороне, и в одном из методов просто создает объект класса унаследованного от IUnknown.
Далее при регистрации классов создается объект фабрики классов, который и создает непосредственно наш класс.
STDAPI DllGetClassObject( REFCLSID rclsid, REFIID riid, void** ppv ) { MathClassFactory *pCF; ....... pCF = new MathClassFactory; ....... }