为了使代码的可维护性好 (换句话说就是代码不动)所以我们选择在dll中添加类工厂
因为不同的功能返回的this指针不同 所以就需要不同的类工厂
因为不同的类工厂又需要大量的switch case 来做判断所以并没有解决根本的问题
所以我们需要添加一个列表,用来记录对应的类
首先对应一个结构体 使工厂和特定id对应
//返回一个类工厂对象 HRESULT __stdcall MyGetClassObject(const GUID & clsid, const GUID & iid, void** ppObject) { static IMyClassFactory *pObject = NULL; if (pObject == NULL) { int count = sizeof(g_factorys) / sizeof(g_factorys[0]); int i; for (i = 0; i < count; i++) { if (memcmp(&clsid, g_factorys[i].clsid, sizeof(GUID)) == 0) { pObject = g_factorys[i].pfn(); break; } } if (i == count) return E_NOINTERFACE; } 最后通过 找到对应的类工厂来调 对应的类对象 HRESULT hr = pObject->QueryInterface(iid, ppObject); if (FAILED(hr) && CSuperStringFactory::m_RefCount == 0) { delete pObject; pObject = NULL; } return hr; }
上面这个函数需要考虑第一次失败 空指针无法释放的问题 和第一次成功第二次失败 释放前面的对象问题
这三个纯虚函数 让所有的继承都必须实现这三个函数的实现,又因为代码几乎相同,造成了大量的重复代码,极度影响了可读性
为了使代码可读性好,所有我们使用了类模板
在其父类和本身类中插一个类 使模板类继承父类 自己继承模板类 模板类则实现 这三个纯虚函数的代码就行了。
template<typename class_name, typename class_base> class ImpIUnknown :public class_base { public: ImpIUnknown(const GUID& iid) :m_iid(iid) { } virtual HRESULT __stdcall QueryInterface(const GUID& iid, void** ppv) { if (memcmp(&iid, &IID_IMyUnkown, sizeof(GUID)) == 0) { *ppv = (IMyUnkown*)this; AddRef(); } else if (memcmp(&iid, &m_iid, sizeof(GUID)) == 0) { *ppv = (class_name*)this; AddRef(); } else return E_NOINTERFACE; return S_OK; } virtual HRESULT __stdcall AddRef() { m_RefCount++; return S_OK; } virtual HRESULT __stdcall Release() { if (--m_RefCount == 0) delete this; return S_OK; } public: static int m_RefCount; const GUID& m_iid; };