我尝试用模板实现静态工厂模式,以a)避免为每个派生类编写相同的代码片段,以及b)回收相同类型的对象。下面的代码可以编译,但不能工作。我不确定这是不是因为我用了智能指针。
这是我的代码:
class ObjMgr
{
public:
static ObjMgr & Instance();
template <typename T>
void Register(const char* name) {
m_creators[name] = &(ObjCreator<T>);
}
Abstract &
GetObj(const string& objTypeCode);
private:
ObjMgr(void) {};
template <typename T>
static shared_ptr<Abstract>& ObjCreator() {
return move(std::shared_ptr<Abstract> (new T));
}
typedef shared_ptr<Abstract>& (*PObjCreator)();
std::unordered_map<std::string, PObjCreator> m_creators;
vector< shared_ptr<Abstract> > m_objs;
//singleton
static unique_ptr<ObjMgr> m_instance;
static std::once_flag m_onceFlag;
ObjMgr(const ObjMgr &) = default;
ObjMgr& operator=(const ObjMgr &) = default;
};
Abstract& ObjMgr::GetObj(const string& objTypeCode)
{
const shared_ptr<Abstract>& obj = m_creators[objTypeCode]();
m_objs.push_back(move(obj));
return *(m_objs.back());
}
代码编译,但在运行时,GetObj
返回一个空引用。在main()
中,派生类型注册为
objMgr.Register<Derived>("Derived");
顺便说一句,我使用了一个向量来保存对象,以便以后可以回收相同类型的对象。
谁能告诉我我做错了什么并告诉我如何改正它?我发现了问题:对象是在ObjCreator()
的堆栈上创建的。我只需要创建静态变量来保存对象:
template <typename T>
static shared_ptr<Abstract>& ObjCreator() {
static vector<shared_ptr<Abstract>> objs;
objs.emplace_back(std::make_shared<T>());
return (objs.back());
}
然后在ObjMgr
中,我将做簿记,看看特定类型的对象是否已经存在,以便我可以回收它。
我想可能是你的Register(const char* name)方法和unordered_map<string,…>处于冲突之中。将unordered_map更改为unordered_map
我无法让你的代码编译。
下面的代码可以工作:
请注意,我通常这样做的方式是使用Singleton
如果你想要能够返回不同的实例,那么改变ObjectManager::CreatorFunc中的代码,使'instance'变量不是静态的,而是一个局部变量,或者传递一个不同的CreatorFunc给Register。
stdafx.h:
#include "targetver.h"
#include <stdio.h>
#include <tchar.h>
#include <unordered_map>
#include <memory>
#include <mutex>
#include <iostream>
cpp:
#include "stdafx.h"
class Abstract
{
};
template <typename T>
class Singleton : public Abstract
{
private:
static T* m_singleton;
public:
static T& Instance()
{
if (m_singleton == 0)
{
m_singleton = new T();
}
return *m_singleton;
}
};
template <typename T> T* Singleton<T>::m_singleton;
class ObjectManager : public Singleton<ObjectManager>
{
private:
typedef Abstract& (*CreatorFuncType)();
std::unordered_map<const char*, CreatorFuncType> m_creators;
template <typename T>
static T& CreatorFunc()
{
static T* const instance = new T();
return *instance;
}
public:
template <typename T>
void Register(const char* name, CreatorFuncType creator = (CreatorFuncType)CreatorFunc<T>)
{
m_creators[name] = creator == 0 ? (CreatorFuncType)Singleton<T>::Instance : creator;
}
Abstract& ObjectManager::GetObj(const char* name)
{
CreatorFuncType creator = m_creators[name];
return (creator)();
}
};
class TestClass : Singleton<TestClass>
{
static int count;
int myInstance;
public:
TestClass()
: myInstance(++count)
{
std::cout << "hello in test class ctor instance #" << myInstance << std::endl;
}
void TestFunc()
{
std::cout << "I'm in the test func with instance #" << myInstance << std::endl;
}
};
int TestClass::count = 0;
int _tmain(int argc, _TCHAR* argv[])
{
ObjectManager::Instance().Register<TestClass>("TestClass");
TestClass &tc = (TestClass&)ObjectManager::Instance().GetObj("TestClass");
TestClass &tc2 = (TestClass&)ObjectManager::Instance().GetObj("TestClass");
std::cout << "tc == tc2 is " << (&tc == &tc2 ? "true" : "false") << std::endl;
std::cout << "tc.... ";
tc.TestFunc();
std::cout << "tc2... ";
tc2.TestFunc();
char buf[100];
std::cin >> buf;
return 0;
}