我正在尝试为 C++ 中的多个抽象工厂创建一个抽象工厂模板并想出了这个。
#define _CRTDBG_MAP_ALLOC
#include <crtdbg.h>
#include <map>
#include <stdio.h>
class Base
{
public:
virtual ~Base() {}
virtual bool Get() = 0;
};
class DerivedA : public Base
{
public:
bool Get()
{
return true;
}
};
class DerivedB : public Base
{
public:
bool Get()
{
return false;
}
};
template <class T>
class Creator
{
public:
virtual ~Creator(){}
virtual T* Create() = 0;
};
template <class T>
class DerivedCreator : public Creator<T>
{
public:
T* Create()
{
return new T;
}
};
template <class T, class Key>
class Factory
{
public:
void Register(Key Id, Creator<T>* Fn)
{
FunctionMap[Id] = Fn;
}
T* Create(Key Id)
{
return FunctionMap[Id]->Create();
}
~Factory()
{
std::map<Key, Creator<T>*>::iterator i = FunctionMap.begin();
while (i != FunctionMap.end())
{
delete (*i).second;
++i;
}
}
private:
std::map<Key, Creator<T>*> FunctionMap;
};
int main(int argc, char** argv[])
{
_CrtSetDbgFlag(_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG) | _CRTDBG_LEAK_CHECK_DF);
//Register
Factory<Base, char*> temp;
temp.Register("DA", (Creator<Base>*)new DerivedCreator<DerivedA>);
temp.Register("DB", (Creator<Base>*)new DerivedCreator<DerivedB>);
//Pointer to base interface
Base* pBase = 0;
//Create and call
pBase = temp.Create("DA");
printf("DerivedA %u\n", pBase->Get());
delete pBase;
//Create and call
pBase = temp.Create("DB");
printf("DerivedB %u\n", pBase->Get());
delete pBase;
return 0;
}
它编译并运行良好,没有内存泄漏(win32 crtdbg),但我不知道这是否真的是做抽象工厂模板的正确方法。
temp.Register("DA", (Creator<Base>*)new DerivedCreator<DerivedA>);
我也想知道上面的那一行。我很困惑为什么我必须投。我不太了解模板,但考虑到模板类和实际类都是派生的,我认为它应该可以正常工作。
该代码实际上可以正常工作,如上所示,甚至可以正常删除而没有内存泄漏。我只是觉得不太舒服。
除了来自 MaNGOS (wow emulator) - https://mangos.svn.sourceforge.net/svnroot/mangos/trunk/src/framework/Dynamic/ObjectRegistry.h 的模板类之外,我还没有找到任何真实的模板类示例。
但我认为我不能在我的项目中使用该方法,因为我计划在我的项目中的某个时间点使用 DLL,并且它使用 CRTP,这违反了我对运行时多态性的要求。
最佳答案
类(class)DerivedCreator<DerivedA>
是 Creator<DerivedA>
不是 Creator<Base>
.
你需要告诉派生模板是什么基类型,这样它才能实现Creator<Base>
的接口(interface)。通过创建派生类型的实例:
// DerivedCreator is Creator<BaseType> which creates a
// DerivedType, not a Creator<DerivedType>
template <class DerivedType, class BaseType>
class DerivedCreator : public Creator<BaseType>
{
public:
BaseType* Create()
{
return new DerivedType;
}
};
// Register
Factory<Base, std::string> temp;
temp.Register("DA", new DerivedCreator<DerivedA, Base>);
temp.Register("DB", new DerivedCreator<DerivedB, Base>);
// or if you want to create lots with the same base:
template <class DerivedType>
class DerivedBaseCreator : public DerivedCreator<DerivedType, Base> {};
//Register
Factory<Base, std::string> temp;
temp.Register("DA", new DerivedBaseCreator<DerivedA>);
temp.Register("DB", new DerivedBaseCreator<DerivedB>);
关于使用模板的 C++ 抽象工厂,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4357500/