我尝试使用模板实现静态工厂模式a)void为每个派生类编写相同的代码片段,以及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");
顺便说一句,我使用了一个向量来保存对象,以便以后可以回收相同类型的对象。
有人能告诉我我做错了什么并告诉我如何纠正它吗?
答案 0 :(得分:1)
我发现了问题:对象是在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
我将进行簿记,以查看特定类型的对象是否已经存在,以便我可以回收它。
答案 1 :(得分:0)
我想也许是你的Register(const char * name)方法和unordered_map&lt; string,...&gt;有冲突。将unordered_map更改为unordered_map&lt; const char *,...&gt;代替。
我无法编译你的代码。
以下代码有效:
请注意,我通常采用的方法是使用Singleton&lt; T&gt;。模板,因为它似乎总是想要获得相同的实例。
如果您希望能够返回不同的实例,请更改ObjectManager :: CreatorFunc中的代码,以便&#39;实例&#39;变量不是静态的,而是局部变量或将不同的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;
}